First Commit
This commit is contained in:
32
3rdparty/shaderc/libshaderc_util/Android.mk
vendored
Normal file
32
3rdparty/shaderc/libshaderc_util/Android.mk
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
# Copyright 2020 The Shaderc Authors. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE:=shaderc_util
|
||||
LOCAL_CXXFLAGS:=-std=c++17 -fno-exceptions -fno-rtti -DENABLE_HLSL=1
|
||||
LOCAL_EXPORT_C_INCLUDES:=$(LOCAL_PATH)/include
|
||||
LOCAL_SRC_FILES:=src/args.cc \
|
||||
src/compiler.cc \
|
||||
src/file_finder.cc \
|
||||
src/io_shaderc.cc \
|
||||
src/message.cc \
|
||||
src/resources.cc \
|
||||
src/shader_stage.cc \
|
||||
src/spirv_tools_wrapper.cc \
|
||||
src/version_profile.cc
|
||||
LOCAL_STATIC_LIBRARIES:=SPIRV SPIRV-Tools-opt
|
||||
LOCAL_C_INCLUDES:=$(LOCAL_PATH)/include
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
89
3rdparty/shaderc/libshaderc_util/CMakeLists.txt
vendored
Normal file
89
3rdparty/shaderc/libshaderc_util/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
# Copyright 2020 The Shaderc Authors. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
project(libshaderc_util)
|
||||
|
||||
add_library(shaderc_util STATIC
|
||||
include/libshaderc_util/counting_includer.h
|
||||
include/libshaderc_util/file_finder.h
|
||||
include/libshaderc_util/format.h
|
||||
include/libshaderc_util/io_shaderc.h
|
||||
include/libshaderc_util/mutex.h
|
||||
include/libshaderc_util/message.h
|
||||
include/libshaderc_util/resources.h
|
||||
include/libshaderc_util/spirv_tools_wrapper.h
|
||||
include/libshaderc_util/string_piece.h
|
||||
include/libshaderc_util/universal_unistd.h
|
||||
include/libshaderc_util/version_profile.h
|
||||
src/args.cc
|
||||
src/compiler.cc
|
||||
src/file_finder.cc
|
||||
src/io_shaderc.cc
|
||||
src/message.cc
|
||||
src/resources.cc
|
||||
src/shader_stage.cc
|
||||
src/spirv_tools_wrapper.cc
|
||||
src/version_profile.cc
|
||||
)
|
||||
|
||||
shaderc_default_compile_options(shaderc_util)
|
||||
target_include_directories(shaderc_util
|
||||
PUBLIC include PRIVATE ${glslang_SOURCE_DIR})
|
||||
# We use parts of Glslang's HLSL compilation interface, which
|
||||
# now requires this preprocessor definition.
|
||||
add_definitions(-DENABLE_HLSL)
|
||||
|
||||
find_package(Threads)
|
||||
target_link_libraries(shaderc_util PRIVATE
|
||||
glslang SPIRV
|
||||
SPIRV-Tools-opt ${CMAKE_THREAD_LIBS_INIT})
|
||||
|
||||
shaderc_add_tests(
|
||||
TEST_PREFIX shaderc_util
|
||||
LINK_LIBS shaderc_util
|
||||
TEST_NAMES
|
||||
counting_includer
|
||||
string_piece
|
||||
format
|
||||
file_finder
|
||||
io_shaderc
|
||||
message
|
||||
mutex
|
||||
version_profile)
|
||||
|
||||
if(${SHADERC_ENABLE_TESTS})
|
||||
target_include_directories(shaderc_util_counting_includer_test
|
||||
PRIVATE ${glslang_SOURCE_DIR})
|
||||
target_include_directories(shaderc_util_version_profile_test
|
||||
PRIVATE ${glslang_SOURCE_DIR})
|
||||
endif()
|
||||
|
||||
shaderc_add_tests(
|
||||
TEST_PREFIX shaderc_util
|
||||
LINK_LIBS shaderc_util
|
||||
INCLUDE_DIRS
|
||||
${glslang_SOURCE_DIR}
|
||||
${spirv-tools_SOURCE_DIR}/include
|
||||
TEST_NAMES
|
||||
compiler)
|
||||
|
||||
# This target copies content of testdata into the build directory.
|
||||
add_custom_target(testdata COMMAND
|
||||
${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/testdata/copy-to-build.cmake
|
||||
COMMENT "Copy testdata into build directory")
|
||||
|
||||
if(${SHADERC_ENABLE_TESTS})
|
||||
add_dependencies(shaderc_util_file_finder_test testdata)
|
||||
add_dependencies(shaderc_util_io_shaderc_test testdata)
|
||||
endif()
|
||||
41
3rdparty/shaderc/libshaderc_util/include/libshaderc_util/args.h
vendored
Normal file
41
3rdparty/shaderc/libshaderc_util/include/libshaderc_util/args.h
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
// Copyright 2019 The Shaderc Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBSHADERC_UTIL_INC_ARGS_H
|
||||
#define LIBSHADERC_UTIL_INC_ARGS_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "libshaderc_util/string_piece.h"
|
||||
|
||||
namespace shaderc_util {
|
||||
|
||||
// Gets the option argument for the option at *index in argv in a way consistent
|
||||
// with clang/gcc. On success, returns true and writes the parsed argument into
|
||||
// *option_argument. Returns false if any errors occur. After calling this
|
||||
// function, *index will be the index of the last command line argument
|
||||
// consumed.
|
||||
bool GetOptionArgument(int argc, char** argv, int* index,
|
||||
const std::string& option,
|
||||
string_piece* option_argument);
|
||||
|
||||
// Parses the given string as a number of the specified type. Returns true
|
||||
// if parsing succeeded, and stores the parsed value via |value|.
|
||||
// (I've worked out the general case for this in
|
||||
// SPIRV-Tools source/util/parse_number.h. -- dneto)
|
||||
bool ParseUint32(const std::string& str, uint32_t* value);
|
||||
|
||||
} // namespace shaderc_util
|
||||
#endif // LIBSHADERC_UTIL_INC_ARGS_H
|
||||
656
3rdparty/shaderc/libshaderc_util/include/libshaderc_util/compiler.h
vendored
Normal file
656
3rdparty/shaderc/libshaderc_util/include/libshaderc_util/compiler.h
vendored
Normal file
@@ -0,0 +1,656 @@
|
||||
// Copyright 2015 The Shaderc Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBSHADERC_UTIL_INC_COMPILER_H
|
||||
#define LIBSHADERC_UTIL_INC_COMPILER_H
|
||||
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
|
||||
#include "glslang/Public/ShaderLang.h"
|
||||
|
||||
#include "counting_includer.h"
|
||||
#include "file_finder.h"
|
||||
#include "mutex.h"
|
||||
#include "resources.h"
|
||||
#include "string_piece.h"
|
||||
|
||||
// Fix a typo in glslang/Public/ShaderLang.h
|
||||
#define EShTargetClientVersion EshTargetClientVersion
|
||||
|
||||
namespace shaderc_util {
|
||||
|
||||
// To break recursive including. This header is already included in
|
||||
// spirv_tools_wrapper.h, so cannot include spirv_tools_wrapper.h here.
|
||||
enum class PassId;
|
||||
|
||||
// Initializes glslang on creation, and destroys it on completion.
|
||||
// Used to tie gslang process operations to object lifetimes.
|
||||
// Additionally initialization/finalization of glslang is not thread safe, so
|
||||
// synchronizes these operations.
|
||||
class GlslangInitializer {
|
||||
public:
|
||||
GlslangInitializer();
|
||||
~GlslangInitializer();
|
||||
|
||||
private:
|
||||
static unsigned int initialize_count_;
|
||||
|
||||
// Using a bare pointer here to avoid any global class construction at the
|
||||
// beginning of the execution.
|
||||
static std::mutex* glslang_mutex_;
|
||||
};
|
||||
|
||||
// Maps macro names to their definitions. Stores string_pieces, so the
|
||||
// underlying strings must outlive it.
|
||||
using MacroDictionary = std::unordered_map<std::string, std::string>;
|
||||
|
||||
// Holds all of the state required to compile source GLSL into SPIR-V.
|
||||
class Compiler {
|
||||
public:
|
||||
// Source language
|
||||
enum class SourceLanguage {
|
||||
GLSL, // The default
|
||||
HLSL,
|
||||
};
|
||||
|
||||
// Target environment.
|
||||
enum class TargetEnv {
|
||||
Vulkan, // Default to Vulkan 1.0
|
||||
OpenGL, // Default to OpenGL 4.5
|
||||
OpenGLCompat, // Support removed. Generates error if used.
|
||||
};
|
||||
|
||||
// Target environment versions. These numbers match those used by Glslang.
|
||||
enum class TargetEnvVersion : uint32_t {
|
||||
Default = 0, // Default for the corresponding target environment
|
||||
// For Vulkan, use numbering scheme from vulkan.h
|
||||
Vulkan_1_0 = ((1 << 22)), // Vulkan 1.0
|
||||
Vulkan_1_1 = ((1 << 22) | (1 << 12)), // Vulkan 1.1
|
||||
Vulkan_1_2 = ((1 << 22) | (2 << 12)), // Vulkan 1.2
|
||||
Vulkan_1_3 = ((1 << 22) | (3 << 12)), // Vulkan 1.2
|
||||
// For OpenGL, use the numbering from #version in shaders.
|
||||
OpenGL_4_5 = 450,
|
||||
};
|
||||
|
||||
// SPIR-V version.
|
||||
enum class SpirvVersion : uint32_t {
|
||||
v1_0 = 0x010000u,
|
||||
v1_1 = 0x010100u,
|
||||
v1_2 = 0x010200u,
|
||||
v1_3 = 0x010300u,
|
||||
v1_4 = 0x010400u,
|
||||
v1_5 = 0x010500u,
|
||||
v1_6 = 0x010600u,
|
||||
};
|
||||
|
||||
enum class OutputType {
|
||||
SpirvBinary, // A binary module, as defined by the SPIR-V specification.
|
||||
SpirvAssemblyText, // Assembly syntax defined by the SPIRV-Tools project.
|
||||
PreprocessedText, // Preprocessed source code.
|
||||
};
|
||||
|
||||
// Supported optimization levels.
|
||||
enum class OptimizationLevel {
|
||||
Zero, // No optimization.
|
||||
Size, // Optimization towards reducing code size.
|
||||
Performance, // Optimization towards better performance.
|
||||
};
|
||||
|
||||
// Resource limits. These map to the "max*" fields in
|
||||
// glslang::TBuiltInResource.
|
||||
enum class Limit {
|
||||
#define RESOURCE(NAME, FIELD, CNAME) NAME,
|
||||
#include "resources.inc"
|
||||
#undef RESOURCE
|
||||
};
|
||||
|
||||
// Types of uniform variables.
|
||||
enum class UniformKind {
|
||||
// Image, and image buffer.
|
||||
Image = 0,
|
||||
// Pure sampler.
|
||||
Sampler = 1,
|
||||
// Sampled texture in GLSL.
|
||||
// Shader Resource View, for HLSL. (Read-only image or storage buffer.)
|
||||
Texture = 2,
|
||||
// Uniform Buffer Object, or UBO, in GLSL.
|
||||
// Also a Cbuffer in HLSL.
|
||||
Buffer = 3,
|
||||
// Shader Storage Buffer Object, or SSBO
|
||||
StorageBuffer = 4,
|
||||
// Uniform Access View, in HLSL. (Writable storage image or storage
|
||||
// buffer.)
|
||||
UnorderedAccessView = 5,
|
||||
};
|
||||
enum { kNumUniformKinds = int(UniformKind::UnorderedAccessView) + 1 };
|
||||
|
||||
// Shader pipeline stage.
|
||||
// TODO(dneto): Replaces interface uses of EShLanguage with this enum.
|
||||
enum class Stage {
|
||||
Vertex,
|
||||
TessEval,
|
||||
TessControl,
|
||||
Geometry,
|
||||
Fragment,
|
||||
Compute,
|
||||
RayGenNV,
|
||||
IntersectNV,
|
||||
AnyHitNV,
|
||||
ClosestHitNV,
|
||||
MissNV,
|
||||
CallableNV,
|
||||
TaskNV,
|
||||
MeshNV,
|
||||
StageEnd,
|
||||
};
|
||||
enum { kNumStages = int(Stage::StageEnd) };
|
||||
|
||||
// Returns a std::array of all the Stage values.
|
||||
const std::array<Stage, kNumStages>& stages() const {
|
||||
static std::array<Stage, kNumStages> values{{
|
||||
Stage::Vertex,
|
||||
Stage::TessEval,
|
||||
Stage::TessControl,
|
||||
Stage::Geometry,
|
||||
Stage::Fragment,
|
||||
Stage::Compute,
|
||||
Stage::RayGenNV,
|
||||
Stage::IntersectNV,
|
||||
Stage::AnyHitNV,
|
||||
Stage::ClosestHitNV,
|
||||
Stage::MissNV,
|
||||
Stage::CallableNV,
|
||||
Stage::TaskNV,
|
||||
Stage::MeshNV,
|
||||
}};
|
||||
return values;
|
||||
}
|
||||
|
||||
// Creates an default compiler instance targeting at Vulkan environment. Uses
|
||||
// version 110 and no profile specification as the default for GLSL.
|
||||
Compiler()
|
||||
// The default version for glsl is 110, or 100 if you are using an es
|
||||
// profile. But we want to default to a non-es profile.
|
||||
: default_version_(110),
|
||||
default_profile_(ENoProfile),
|
||||
force_version_profile_(false),
|
||||
warnings_as_errors_(false),
|
||||
suppress_warnings_(false),
|
||||
generate_debug_info_(false),
|
||||
emit_non_semantic_debug_info_(false),
|
||||
enabled_opt_passes_(),
|
||||
target_env_(TargetEnv::Vulkan),
|
||||
target_env_version_(TargetEnvVersion::Default),
|
||||
target_spirv_version_(SpirvVersion::v1_0),
|
||||
target_spirv_version_is_forced_(false),
|
||||
source_language_(SourceLanguage::GLSL),
|
||||
limits_(kDefaultTBuiltInResource),
|
||||
auto_bind_uniforms_(false),
|
||||
auto_combined_image_sampler_(false),
|
||||
auto_binding_base_(),
|
||||
auto_map_locations_(false),
|
||||
preserve_bindings_(false),
|
||||
hlsl_iomap_(false),
|
||||
hlsl_offsets_(false),
|
||||
hlsl_legalization_enabled_(true),
|
||||
hlsl_functionality1_enabled_(false),
|
||||
hlsl_16bit_types_enabled_(false),
|
||||
invert_y_enabled_(false),
|
||||
nan_clamp_(false),
|
||||
hlsl_explicit_bindings_() {}
|
||||
|
||||
// Requests that the compiler place debug information into the object code,
|
||||
// such as identifier names and line numbers.
|
||||
void SetGenerateDebugInfo();
|
||||
|
||||
// Requests that the compiler emit non-semantic debug information.
|
||||
// Requires VK_KHR_shader_non_semantic_info.
|
||||
void SetEmitNonSemanticDebugInfo();
|
||||
|
||||
// Sets the optimization level to the given level. Only the last one takes
|
||||
// effect if multiple calls of this method exist.
|
||||
void SetOptimizationLevel(OptimizationLevel level);
|
||||
|
||||
// Enables or disables HLSL legalization passes.
|
||||
void EnableHlslLegalization(bool hlsl_legalization_enabled);
|
||||
|
||||
// Enables or disables extension SPV_GOOGLE_hlsl_functionality1
|
||||
void EnableHlslFunctionality1(bool enable);
|
||||
|
||||
// Enables or disables HLSL 16-bit types.
|
||||
void EnableHlsl16BitTypes(bool enable);
|
||||
|
||||
// Enables or disables relaxed Vulkan rules.
|
||||
//
|
||||
// This allows most OpenGL shaders to compile under Vulkan semantics.
|
||||
void SetVulkanRulesRelaxed(bool enable);
|
||||
|
||||
// Enables or disables invert position.Y output in vertex shader.
|
||||
void EnableInvertY(bool enable);
|
||||
|
||||
// Sets whether the compiler generates code for max and min builtins which,
|
||||
// if given a NaN operand, will return the other operand. Also, the clamp
|
||||
// builtin will favour the non-NaN operands, as if clamp were implemented
|
||||
// as a composition of max and min.
|
||||
void SetNanClamp(bool enable);
|
||||
|
||||
// When a warning is encountered it treat it as an error.
|
||||
void SetWarningsAsErrors();
|
||||
|
||||
// Any warning message generated is suppressed before it is output.
|
||||
void SetSuppressWarnings();
|
||||
|
||||
// Adds an implicit macro definition obeyed by subsequent CompileShader()
|
||||
// calls. The macro and definition should be passed in with their char*
|
||||
// pointer and their lengths. They can be modified or deleted after this
|
||||
// function has returned.
|
||||
void AddMacroDefinition(const char* macro, size_t macro_length,
|
||||
const char* definition, size_t definition_length);
|
||||
|
||||
// Sets the target environment, including version. The version value should
|
||||
// be 0 or one of the values from TargetEnvVersion. The default value maps
|
||||
// to Vulkan 1.0 if the target environment is Vulkan, and it maps to OpenGL
|
||||
// 4.5 if the target environment is OpenGL.
|
||||
void SetTargetEnv(TargetEnv env,
|
||||
TargetEnvVersion version = TargetEnvVersion::Default);
|
||||
|
||||
// Sets the target version of SPIR-V. The module will use this version
|
||||
// of SPIR-V. Defaults to the highest version of SPIR-V required to be
|
||||
// supported by the target environment. E.g. default to SPIR-V 1.0 for
|
||||
// Vulkan 1.0, and SPIR-V 1.3 for Vulkan 1.1.
|
||||
void SetTargetSpirv(SpirvVersion version);
|
||||
|
||||
// Sets the souce language.
|
||||
void SetSourceLanguage(SourceLanguage lang);
|
||||
|
||||
// Forces (without any verification) the default version and profile for
|
||||
// subsequent CompileShader() calls.
|
||||
void SetForcedVersionProfile(int version, EProfile profile);
|
||||
|
||||
// Sets a resource limit.
|
||||
void SetLimit(Limit limit, int value);
|
||||
|
||||
// Returns the current limit.
|
||||
int GetLimit(Limit limit) const;
|
||||
|
||||
// Set whether the compiler automatically assigns bindings to
|
||||
// uniform variables that don't have explicit bindings.
|
||||
void SetAutoBindUniforms(bool auto_bind) { auto_bind_uniforms_ = auto_bind; }
|
||||
|
||||
// Sets whether the compiler should automatically remove sampler variables
|
||||
// and convert image variables to combined image-sampler variables.
|
||||
void SetAutoCombinedImageSampler(bool auto_combine) {
|
||||
auto_combined_image_sampler_ = auto_combine;
|
||||
}
|
||||
|
||||
// Sets the lowest binding number used when automatically assigning bindings
|
||||
// for uniform resources of the given type, for all shader stages. The default
|
||||
// base is zero.
|
||||
void SetAutoBindingBase(UniformKind kind, uint32_t base) {
|
||||
for (auto stage : stages()) {
|
||||
SetAutoBindingBaseForStage(stage, kind, base);
|
||||
}
|
||||
}
|
||||
|
||||
// Sets the lowest binding number used when automatically assigning bindings
|
||||
// for uniform resources of the given type for a specific shader stage. The
|
||||
// default base is zero.
|
||||
void SetAutoBindingBaseForStage(Stage stage, UniformKind kind,
|
||||
uint32_t base) {
|
||||
auto_binding_base_[static_cast<int>(stage)][static_cast<int>(kind)] = base;
|
||||
}
|
||||
|
||||
// Sets whether the compiler should preserve all bindings, even when those
|
||||
// bindings are not used.
|
||||
void SetPreserveBindings(bool preserve_bindings) {
|
||||
preserve_bindings_ = preserve_bindings;
|
||||
}
|
||||
|
||||
// Sets whether the compiler automatically assigns locations to
|
||||
// uniform variables that don't have explicit locations.
|
||||
void SetAutoMapLocations(bool auto_map) { auto_map_locations_ = auto_map; }
|
||||
|
||||
// Use HLSL IO mapping rules for bindings. Default is false.
|
||||
void SetHlslIoMapping(bool hlsl_iomap) { hlsl_iomap_ = hlsl_iomap; }
|
||||
|
||||
// Use HLSL rules for offsets in "transparent" memory. These allow for
|
||||
// tighter packing of some combinations of types than standard GLSL packings.
|
||||
void SetHlslOffsets(bool hlsl_offsets) { hlsl_offsets_ = hlsl_offsets; }
|
||||
|
||||
// Sets an explicit set and binding for the given HLSL register.
|
||||
void SetHlslRegisterSetAndBinding(const std::string& reg,
|
||||
const std::string& set,
|
||||
const std::string& binding) {
|
||||
for (auto stage : stages()) {
|
||||
SetHlslRegisterSetAndBindingForStage(stage, reg, set, binding);
|
||||
}
|
||||
}
|
||||
|
||||
// Sets an explicit set and binding for the given HLSL register in the given
|
||||
// shader stage. For example,
|
||||
// SetHlslRegisterSetAndBinding(Stage::Fragment, "t1", "4", "5")
|
||||
// means register "t1" in a fragment shader should map to binding 5 in set 4.
|
||||
// (Glslang wants this data as strings, not ints or enums.) The string data is
|
||||
// copied.
|
||||
void SetHlslRegisterSetAndBindingForStage(Stage stage, const std::string& reg,
|
||||
const std::string& set,
|
||||
const std::string& binding) {
|
||||
hlsl_explicit_bindings_[static_cast<int>(stage)].push_back(reg);
|
||||
hlsl_explicit_bindings_[static_cast<int>(stage)].push_back(set);
|
||||
hlsl_explicit_bindings_[static_cast<int>(stage)].push_back(binding);
|
||||
}
|
||||
|
||||
// Compiles the shader source in the input_source_string parameter.
|
||||
//
|
||||
// If the forced_shader stage parameter is not EShLangCount then
|
||||
// the shader is assumed to be of the given stage.
|
||||
//
|
||||
// For HLSL compilation, entry_point_name is the null-terminated string for
|
||||
// the entry point. For GLSL compilation, entry_point_name is ignored, and
|
||||
// compilation assumes the entry point is named "main".
|
||||
//
|
||||
// The stage_callback function will be called if a shader_stage has
|
||||
// not been forced and the stage can not be determined
|
||||
// from the shader text. Any #include directives are parsed with the given
|
||||
// includer.
|
||||
//
|
||||
// The initializer parameter must be a valid GlslangInitializer object.
|
||||
// Acquire will be called on the initializer and the result will be
|
||||
// destroyed before the function ends.
|
||||
//
|
||||
// The output_type parameter determines what kind of output should be
|
||||
// produced.
|
||||
//
|
||||
// Any error messages are written as if the file name were error_tag.
|
||||
// Any errors are written to the error_stream parameter.
|
||||
// total_warnings and total_errors are incremented once for every
|
||||
// warning or error encountered respectively.
|
||||
//
|
||||
// Returns a tuple consisting of three fields. 1) a boolean which is true when
|
||||
// the compilation succeeded, and false otherwise; 2) a vector of 32-bit words
|
||||
// which contains the compilation output data, either compiled SPIR-V binary
|
||||
// code, or the text string generated in preprocessing-only or disassembly
|
||||
// mode; 3) the size of the output data in bytes. When the output is SPIR-V
|
||||
// binary code, the size is the number of bytes of valid data in the vector.
|
||||
// If the output is a text string, the size equals the length of that string.
|
||||
std::tuple<bool, std::vector<uint32_t>, size_t> Compile(
|
||||
const string_piece& input_source_string, EShLanguage forced_shader_stage,
|
||||
const std::string& error_tag, const char* entry_point_name,
|
||||
const std::function<EShLanguage(std::ostream* error_stream,
|
||||
const string_piece& error_tag)>&
|
||||
stage_callback,
|
||||
CountingIncluder& includer, OutputType output_type,
|
||||
std::ostream* error_stream, size_t* total_warnings, size_t* total_errors) const;
|
||||
|
||||
static EShMessages GetDefaultRules() {
|
||||
return static_cast<EShMessages>(EShMsgSpvRules | EShMsgVulkanRules |
|
||||
EShMsgCascadingErrors);
|
||||
}
|
||||
|
||||
protected:
|
||||
// Preprocesses a shader whose filename is filename and content is
|
||||
// shader_source. If preprocessing is successful, returns true, the
|
||||
// preprocessed shader, and any warning message as a tuple. Otherwise,
|
||||
// returns false, an empty string, and error messages as a tuple.
|
||||
//
|
||||
// The error_tag parameter is the name to use for outputting errors.
|
||||
// The shader_source parameter is the input shader's source text.
|
||||
// The shader_preamble parameter is a context-specific preamble internally
|
||||
// prepended to shader_text without affecting the validity of its #version
|
||||
// position.
|
||||
//
|
||||
// Any #include directives are processed with the given includer.
|
||||
//
|
||||
// If force_version_profile_ is set, the shader's version/profile is forced
|
||||
// to be default_version_/default_profile_ regardless of the #version
|
||||
// directive in the source code.
|
||||
std::tuple<bool, std::string, std::string> PreprocessShader(
|
||||
const std::string& error_tag, const string_piece& shader_source,
|
||||
const string_piece& shader_preamble, CountingIncluder& includer) const;
|
||||
|
||||
// Cleans up the preamble in a given preprocessed shader.
|
||||
//
|
||||
// The error_tag parameter is the name to be given for the main file.
|
||||
// The pound_extension parameter is the #extension directive we prepended to
|
||||
// the original shader source code via preamble.
|
||||
// The num_include_directives parameter is the number of #include directives
|
||||
// appearing in the original shader source code.
|
||||
// The is_for_next_line means whether the #line sets the line number for the
|
||||
// next line.
|
||||
//
|
||||
// If no #include directive is used in the shader source code, we can safely
|
||||
// delete the #extension directive we injected via preamble. Otherwise, we
|
||||
// need to adjust it if there exists a #version directive in the original
|
||||
// shader source code.
|
||||
std::string CleanupPreamble(const string_piece& preprocessed_shader,
|
||||
const string_piece& error_tag,
|
||||
const string_piece& pound_extension,
|
||||
int num_include_directives,
|
||||
bool is_for_next_line) const;
|
||||
|
||||
// Determines version and profile from command line, or the source code.
|
||||
// Returns the decoded version and profile pair on success. Otherwise,
|
||||
// returns (0, ENoProfile).
|
||||
std::pair<int, EProfile> DeduceVersionProfile(
|
||||
const std::string& preprocessed_shader) const;
|
||||
|
||||
// Determines the shader stage from pragmas embedded in the source text if
|
||||
// possible. In the returned pair, the glslang EShLanguage is the shader
|
||||
// stage deduced. If no #pragma directives for shader stage exist, it's
|
||||
// EShLangCount. If errors occur, the second element in the pair is the
|
||||
// error message. Otherwise, it's an empty string.
|
||||
std::pair<EShLanguage, std::string> GetShaderStageFromSourceCode(
|
||||
string_piece filename, const std::string& preprocessed_shader) const;
|
||||
|
||||
// Determines version and profile from command line, or the source code.
|
||||
// Returns the decoded version and profile pair on success. Otherwise,
|
||||
// returns (0, ENoProfile).
|
||||
std::pair<int, EProfile> DeduceVersionProfile(
|
||||
const std::string& preprocessed_shader);
|
||||
|
||||
// Gets version and profile specification from the given preprocessedshader.
|
||||
// Returns the decoded version and profile pair on success. Otherwise,
|
||||
// returns (0, ENoProfile).
|
||||
std::pair<int, EProfile> GetVersionProfileFromSourceCode(
|
||||
const std::string& preprocessed_shader) const;
|
||||
|
||||
// Version to use when force_version_profile_ is true.
|
||||
int default_version_;
|
||||
// Profile to use when force_version_profile_ is true.
|
||||
EProfile default_profile_;
|
||||
// When true, use the default version and profile from eponymous data members.
|
||||
bool force_version_profile_;
|
||||
|
||||
// Macro definitions that must be available to reference in the shader source.
|
||||
MacroDictionary predefined_macros_;
|
||||
|
||||
// When true, treat warnings as errors.
|
||||
bool warnings_as_errors_;
|
||||
// Supress warnings when true.
|
||||
bool suppress_warnings_;
|
||||
|
||||
// When true, compilation will generate debug info with the binary SPIR-V
|
||||
// output.
|
||||
bool generate_debug_info_;
|
||||
|
||||
// When true and generate_debug_info_ is also set, generate non-semantic debug
|
||||
// information.
|
||||
bool emit_non_semantic_debug_info_;
|
||||
|
||||
// Optimization passes to be applied.
|
||||
std::vector<PassId> enabled_opt_passes_;
|
||||
|
||||
// The target environment to compile with. This controls the glslang
|
||||
// EshMessages bitmask, which determines which dialect of GLSL and which
|
||||
// SPIR-V codegen semantics are used. This impacts the warning & error
|
||||
// messages as well as the set of available builtins, as per the
|
||||
// implementation of glslang.
|
||||
TargetEnv target_env_;
|
||||
|
||||
// The version number of the target environment. The numbering scheme is
|
||||
// particular to each target environment. If this is 0, then use a default
|
||||
// for that particular target environment. See libshaders/shaderc/shaderc.h
|
||||
// for those defaults.
|
||||
TargetEnvVersion target_env_version_;
|
||||
|
||||
// The SPIR-V version to be used for the generated module. Defaults to 1.0.
|
||||
SpirvVersion target_spirv_version_;
|
||||
// True if the user explicitly set the target SPIR-V version.
|
||||
bool target_spirv_version_is_forced_;
|
||||
|
||||
// The source language. Defaults to GLSL.
|
||||
SourceLanguage source_language_;
|
||||
|
||||
// The resource limits to be used.
|
||||
TBuiltInResource limits_;
|
||||
|
||||
// True if the compiler should automatically bind uniforms that don't
|
||||
// have explicit bindings.
|
||||
bool auto_bind_uniforms_;
|
||||
|
||||
// True if the compiler should automatically remove sampler variables
|
||||
// and convert image variables to combined image-sampler variables.
|
||||
bool auto_combined_image_sampler_;
|
||||
|
||||
// The base binding number per uniform type, per stage, used when automatically
|
||||
// binding uniforms that don't hzve explicit bindings in the shader source.
|
||||
// The default is zero.
|
||||
uint32_t auto_binding_base_[kNumStages][kNumUniformKinds];
|
||||
|
||||
// True if the compiler should automatically map uniforms that don't
|
||||
// have explicit locations.
|
||||
bool auto_map_locations_;
|
||||
|
||||
// True if the compiler should preserve all bindings, even when unused.
|
||||
bool preserve_bindings_;
|
||||
|
||||
// True if the compiler should use HLSL IO mapping rules when compiling HLSL.
|
||||
bool hlsl_iomap_;
|
||||
|
||||
// True if the compiler should determine block member offsets using HLSL
|
||||
// packing rules instead of standard GLSL rules.
|
||||
bool hlsl_offsets_;
|
||||
|
||||
// True if the compiler should perform legalization optimization passes if
|
||||
// source language is HLSL.
|
||||
bool hlsl_legalization_enabled_;
|
||||
|
||||
// True if the compiler should support extension SPV_GOOGLE_hlsl_functionality1.
|
||||
bool hlsl_functionality1_enabled_;
|
||||
|
||||
// True if the compiler should support 16-bit HLSL types.
|
||||
bool hlsl_16bit_types_enabled_;
|
||||
|
||||
// True if the compiler should relax Vulkan rules to allow OGL shaders to
|
||||
// compile.
|
||||
bool vulkan_rules_relaxed_ = false;
|
||||
|
||||
// True if the compiler should invert position.Y output in vertex shader.
|
||||
bool invert_y_enabled_;
|
||||
|
||||
// True if the compiler generates code for max and min builtins which,
|
||||
// if given a NaN operand, will return the other operand. Also, the clamp
|
||||
// builtin will favour the non-NaN operands, as if clamp were implemented
|
||||
// as a composition of max and min.
|
||||
bool nan_clamp_;
|
||||
|
||||
// A sequence of triples, each triple representing a specific HLSL register
|
||||
// name, and the set and binding numbers it should be mapped to, but in
|
||||
// the form of strings. This is how Glslang wants to consume the data.
|
||||
std::vector<std::string> hlsl_explicit_bindings_[kNumStages];
|
||||
};
|
||||
|
||||
// Converts a string to a vector of uint32_t by copying the content of a given
|
||||
// string to the vector and returns it. Appends '\0' at the end if extra bytes
|
||||
// are required to complete the last element.
|
||||
std::vector<uint32_t> ConvertStringToVector(const std::string& str);
|
||||
|
||||
// Converts a valid Glslang shader stage value to a Compiler::Stage value.
|
||||
inline Compiler::Stage ConvertToStage(EShLanguage stage) {
|
||||
switch (stage) {
|
||||
case EShLangVertex:
|
||||
return Compiler::Stage::Vertex;
|
||||
case EShLangTessControl:
|
||||
return Compiler::Stage::TessEval;
|
||||
case EShLangTessEvaluation:
|
||||
return Compiler::Stage::TessControl;
|
||||
case EShLangGeometry:
|
||||
return Compiler::Stage::Geometry;
|
||||
case EShLangFragment:
|
||||
return Compiler::Stage::Fragment;
|
||||
case EShLangCompute:
|
||||
return Compiler::Stage::Compute;
|
||||
case EShLangRayGenNV:
|
||||
return Compiler::Stage::RayGenNV;
|
||||
case EShLangIntersectNV:
|
||||
return Compiler::Stage::IntersectNV;
|
||||
case EShLangAnyHitNV:
|
||||
return Compiler::Stage::AnyHitNV;
|
||||
case EShLangClosestHitNV:
|
||||
return Compiler::Stage::ClosestHitNV;
|
||||
case EShLangMissNV:
|
||||
return Compiler::Stage::MissNV;
|
||||
case EShLangCallableNV:
|
||||
return Compiler::Stage::CallableNV;
|
||||
case EShLangTaskNV:
|
||||
return Compiler::Stage::TaskNV;
|
||||
case EShLangMeshNV:
|
||||
return Compiler::Stage::MeshNV;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
assert(false && "Invalid case");
|
||||
return Compiler::Stage::Compute;
|
||||
}
|
||||
|
||||
// A GlslangClientInfo captures target client version and desired SPIR-V
|
||||
// version.
|
||||
struct GlslangClientInfo {
|
||||
GlslangClientInfo() {}
|
||||
GlslangClientInfo(const std::string& e, glslang::EShClient c,
|
||||
glslang::EShTargetClientVersion cv,
|
||||
glslang::EShTargetLanguage l,
|
||||
glslang::EShTargetLanguageVersion lv)
|
||||
: error(e),
|
||||
client(c),
|
||||
client_version(cv),
|
||||
target_language(l),
|
||||
target_language_version(lv) {}
|
||||
|
||||
std::string error; // Empty if ok, otherwise contains the error message.
|
||||
glslang::EShClient client = glslang::EShClientNone;
|
||||
glslang::EShTargetClientVersion client_version;
|
||||
glslang::EShTargetLanguage target_language = glslang::EShTargetSpv;
|
||||
glslang::EShTargetLanguageVersion target_language_version =
|
||||
glslang::EShTargetSpv_1_0;
|
||||
};
|
||||
|
||||
// Returns the mappings to Glslang client, client version, and SPIR-V version.
|
||||
// Also indicates whether the input values were valid.
|
||||
GlslangClientInfo GetGlslangClientInfo(
|
||||
const std::string& error_tag, // Indicates source location, for errors.
|
||||
shaderc_util::Compiler::TargetEnv env,
|
||||
shaderc_util::Compiler::TargetEnvVersion env_version,
|
||||
shaderc_util::Compiler::SpirvVersion spv_version,
|
||||
bool spv_version_is_forced);
|
||||
|
||||
} // namespace shaderc_util
|
||||
#endif // LIBSHADERC_UTIL_INC_COMPILER_H
|
||||
101
3rdparty/shaderc/libshaderc_util/include/libshaderc_util/counting_includer.h
vendored
Normal file
101
3rdparty/shaderc/libshaderc_util/include/libshaderc_util/counting_includer.h
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
// Copyright 2015 The Shaderc Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBSHADERC_UTIL_COUNTING_INCLUDER_H
|
||||
#define LIBSHADERC_UTIL_COUNTING_INCLUDER_H
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include "glslang/Public/ShaderLang.h"
|
||||
|
||||
#include "libshaderc_util/mutex.h"
|
||||
|
||||
namespace shaderc_util {
|
||||
|
||||
// An Includer that counts how many #include directives it saw.
|
||||
// Inclusions are internally serialized, but releasing a previous result
|
||||
// can occur concurrently.
|
||||
class CountingIncluder : public glslang::TShader::Includer {
|
||||
public:
|
||||
// Done as .store(0) instead of in the initializer list for the following
|
||||
// reasons:
|
||||
// Clang > 3.6 will complain about it if it is written as ({0}).
|
||||
// VS2013 fails if it is written as {0}.
|
||||
// G++-4.8 does not correctly support std::atomic_init.
|
||||
CountingIncluder() {
|
||||
num_include_directives_.store(0);
|
||||
}
|
||||
|
||||
enum class IncludeType {
|
||||
System, // Only do < > include search
|
||||
Local, // Only do " " include search
|
||||
};
|
||||
|
||||
// Resolves an include request for a source by name, type, and name of the
|
||||
// requesting source. For the semantics of the result, see the base class.
|
||||
// Also increments num_include_directives and returns the results of
|
||||
// include_delegate(filename). Subclasses should override include_delegate()
|
||||
// instead of this method. Inclusions are serialized.
|
||||
glslang::TShader::Includer::IncludeResult* includeSystem(
|
||||
const char* requested_source, const char* requesting_source,
|
||||
size_t include_depth) final {
|
||||
++num_include_directives_;
|
||||
include_mutex_.lock();
|
||||
auto result = include_delegate(requested_source, requesting_source,
|
||||
IncludeType::System, include_depth);
|
||||
include_mutex_.unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
// Like includeSystem, but for "local" include search.
|
||||
glslang::TShader::Includer::IncludeResult* includeLocal(
|
||||
const char* requested_source, const char* requesting_source,
|
||||
size_t include_depth) final {
|
||||
++num_include_directives_;
|
||||
include_mutex_.lock();
|
||||
auto result = include_delegate(requested_source, requesting_source,
|
||||
IncludeType::Local, include_depth);
|
||||
include_mutex_.unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
// Releases the given IncludeResult.
|
||||
void releaseInclude(glslang::TShader::Includer::IncludeResult* result) final {
|
||||
release_delegate(result);
|
||||
}
|
||||
|
||||
int num_include_directives() const { return num_include_directives_.load(); }
|
||||
|
||||
private:
|
||||
|
||||
// Invoked by this class to provide results to
|
||||
// glslang::TShader::Includer::include.
|
||||
virtual glslang::TShader::Includer::IncludeResult* include_delegate(
|
||||
const char* requested_source, const char* requesting_source,
|
||||
IncludeType type, size_t include_depth) = 0;
|
||||
|
||||
// Release the given IncludeResult.
|
||||
virtual void release_delegate(
|
||||
glslang::TShader::Includer::IncludeResult* result) = 0;
|
||||
|
||||
// The number of #include directive encountered.
|
||||
std::atomic_int num_include_directives_;
|
||||
|
||||
// A mutex to protect against concurrent inclusions. We can't trust
|
||||
// our delegates to be safe for concurrent inclusions.
|
||||
shaderc_util::mutex include_mutex_;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // LIBSHADERC_UTIL_COUNTING_INCLUDER_H
|
||||
26
3rdparty/shaderc/libshaderc_util/include/libshaderc_util/exceptions.h
vendored
Normal file
26
3rdparty/shaderc/libshaderc_util/include/libshaderc_util/exceptions.h
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
// Copyright 2018 The Shaderc Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBSHADERC_UTIL_EXCEPTIONS_H_
|
||||
#define LIBSHADERC_UTIL_EXCEPTIONS_H_
|
||||
|
||||
#if (defined(_MSC_VER) && !defined(_CPPUNWIND)) || !defined(__EXCEPTIONS)
|
||||
#define TRY_IF_EXCEPTIONS_ENABLED
|
||||
#define CATCH_IF_EXCEPTIONS_ENABLED(X) if (0)
|
||||
#else
|
||||
#define TRY_IF_EXCEPTIONS_ENABLED try
|
||||
#define CATCH_IF_EXCEPTIONS_ENABLED(X) catch (X)
|
||||
#endif
|
||||
|
||||
#endif // LIBSHADERC_UTIL_EXCEPTIONS_H_
|
||||
57
3rdparty/shaderc/libshaderc_util/include/libshaderc_util/file_finder.h
vendored
Normal file
57
3rdparty/shaderc/libshaderc_util/include/libshaderc_util/file_finder.h
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
// Copyright 2015 The Shaderc Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBSHADERC_UTIL_SRC_FILE_FINDER_H_
|
||||
#define LIBSHADERC_UTIL_SRC_FILE_FINDER_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace shaderc_util {
|
||||
|
||||
// Finds files within a search path.
|
||||
class FileFinder {
|
||||
public:
|
||||
// Searches for a read-openable file based on filename, which must be
|
||||
// non-empty. The search is attempted on filename prefixed by each element of
|
||||
// search_path() in turn. The first hit is returned, or an empty string if
|
||||
// there are no hits. Search attempts treat their argument the way
|
||||
// std::fopen() treats its filename argument, ignoring whether the path is
|
||||
// absolute or relative.
|
||||
//
|
||||
// If a search_path() element is non-empty and not ending in a slash, then a
|
||||
// slash is inserted between it and filename before its search attempt. An
|
||||
// empty string in search_path() means that the filename is tried as-is.
|
||||
std::string FindReadableFilepath(const std::string& filename) const;
|
||||
|
||||
// Searches for a read-openable file based on filename, which must be
|
||||
// non-empty. The search is first attempted as a path relative to
|
||||
// the requesting_file parameter. If no file is found relative to the
|
||||
// requesting_file then this acts as FindReadableFilepath does. If
|
||||
// requesting_file does not contain a '/' or a '\' character then it is
|
||||
// assumed to be a filename and the request will be relative to the
|
||||
// current directory.
|
||||
std::string FindRelativeReadableFilepath(const std::string& requesting_file,
|
||||
const std::string& filename) const;
|
||||
|
||||
// Search path for Find(). Users may add/remove elements as desired.
|
||||
std::vector<std::string>& search_path() { return search_path_; }
|
||||
|
||||
private:
|
||||
std::vector<std::string> search_path_;
|
||||
};
|
||||
|
||||
} // namespace shaderc_util
|
||||
|
||||
#endif // LIBSHADERC_UTIL_SRC_FILE_FINDER_H_
|
||||
36
3rdparty/shaderc/libshaderc_util/include/libshaderc_util/format.h
vendored
Normal file
36
3rdparty/shaderc/libshaderc_util/include/libshaderc_util/format.h
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
// Copyright 2015 The Shaderc Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBSHADERC_UTIL_FORMAT_H_
|
||||
#define LIBSHADERC_UTIL_FORMAT_H_
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace shaderc_util {
|
||||
|
||||
// Returns a string containing <prefix><key><infix><value><postfix> for every
|
||||
// key-value entry in map.
|
||||
template <typename Map>
|
||||
std::string format(const Map& map, const std::string& prefix,
|
||||
const std::string& infix, const std::string& postfix) {
|
||||
std::stringstream s;
|
||||
for (const auto& pair : map) {
|
||||
s << prefix << pair.first << infix << pair.second << postfix;
|
||||
}
|
||||
return s.str();
|
||||
}
|
||||
|
||||
} // namespace shaderc_util
|
||||
|
||||
#endif // LIBSHADERC_UTIL_FORMAT_H_
|
||||
69
3rdparty/shaderc/libshaderc_util/include/libshaderc_util/io_shaderc.h
vendored
Normal file
69
3rdparty/shaderc/libshaderc_util/include/libshaderc_util/io_shaderc.h
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
// Copyright 2015 The Shaderc Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBSHADERC_UTIL_IO_H_
|
||||
#define LIBSHADERC_UTIL_IO_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "string_piece.h"
|
||||
|
||||
namespace shaderc_util {
|
||||
|
||||
// Returns true if the given path is an absolute path.
|
||||
bool IsAbsolutePath(const std::string& path);
|
||||
|
||||
// A helper function to return the base file name from either absolute path or
|
||||
// relative path representation of a file. It keeps the component from the last
|
||||
// '/' or '\' to the end of the given string. If the component is '..' or '.',
|
||||
// returns an empty string. If '/' or '\' is the last char of the given string,
|
||||
// also returns an empty string.
|
||||
// e.g.: dir_a/dir_b/file_c.vert => file_c.vert
|
||||
// dir_a/dir_b/.. => <empty string>
|
||||
// dir_a/dir_b/. => <empty string>
|
||||
// dir_a/dirb/c/ => <empty string>
|
||||
// Note that this method doesn't check whether the given path is a valid one or
|
||||
// not.
|
||||
std::string GetBaseFileName(const std::string& file_path);
|
||||
|
||||
// Reads all of the characters in a given file into input_data. Outputs an
|
||||
// error message to std::cerr if the file could not be read and returns false if
|
||||
// there was an error. If the input_file is "-", then input is read from
|
||||
// std::cin.
|
||||
bool ReadFile(const std::string& input_file_name,
|
||||
std::vector<char>* input_data);
|
||||
|
||||
// Returns and initializes the file_stream parameter if the output_filename
|
||||
// refers to a file, or returns &std::cout if the output_filename is "-".
|
||||
// Returns nullptr and emits an error message to err if the file could
|
||||
// not be opened for writing. If the output refers to a file, and the open
|
||||
// failed for writing, file_stream is left with its fail_bit set.
|
||||
std::ostream* GetOutputStream(const string_piece& output_filename,
|
||||
std::ofstream* file_stream, std::ostream* err);
|
||||
|
||||
// Writes output_data to a file, overwriting if it exists. If output_file_name
|
||||
// is "-", writes to std::cout.
|
||||
bool WriteFile(std::ostream* output_stream, const string_piece& output_data);
|
||||
|
||||
// Flush the standard output stream and set it to binary mode. Subsequent
|
||||
// output will not translate newlines to carriage-return newline pairs.
|
||||
void FlushAndSetBinaryModeOnStdout();
|
||||
// Flush the standard output stream and set it to text mode. Subsequent
|
||||
// output will translate newlines to carriage-return newline pairs.
|
||||
void FlushAndSetTextModeOnStdout();
|
||||
|
||||
} // namespace shaderc_util
|
||||
|
||||
#endif // LIBSHADERC_UTIL_IO_H_
|
||||
86
3rdparty/shaderc/libshaderc_util/include/libshaderc_util/message.h
vendored
Normal file
86
3rdparty/shaderc/libshaderc_util/include/libshaderc_util/message.h
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
// Copyright 2015 The Shaderc Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBSHADERC_UTIL_SRC_MESSAGE_H_
|
||||
#define LIBSHADERC_UTIL_SRC_MESSAGE_H_
|
||||
|
||||
#include "libshaderc_util/string_piece.h"
|
||||
|
||||
namespace shaderc_util {
|
||||
|
||||
// TODO(antiagainst): document the differences of the following message types.
|
||||
enum class MessageType {
|
||||
Warning,
|
||||
Error,
|
||||
ErrorSummary,
|
||||
WarningSummary,
|
||||
GlobalWarning,
|
||||
GlobalError,
|
||||
Unknown,
|
||||
Ignored
|
||||
};
|
||||
|
||||
// Given a glslang warning/error message, processes it in the following way and
|
||||
// returns its message type.
|
||||
//
|
||||
// * Places the source name into the source_name parameter, if found.
|
||||
// Otherwise, clears the source_name parameter.
|
||||
// * Places the line number into the line_number parameter, if found.
|
||||
// Otherwise, clears the line_number parameter.
|
||||
// * Places the rest of the message (the text past warning/error prefix, source
|
||||
// name, and line number) into the rest parameter.
|
||||
//
|
||||
// If warnings_as_errors is set to true, then all warnings will be treated as
|
||||
// errors.
|
||||
// If suppress_warnings is set to true, then no warnings will be emitted. This
|
||||
// takes precedence over warnings_as_errors.
|
||||
//
|
||||
// Examples:
|
||||
// "ERROR: 0:2: Message"
|
||||
// source_name="0", line_number="2", rest="Message"
|
||||
// "Warning, Message"
|
||||
// source_name="", line_number="", rest="Message"
|
||||
// "ERROR: 2 errors found."
|
||||
// source_name="2", line_number="", rest="errors found".
|
||||
//
|
||||
// Note that filenames can contain colons:
|
||||
// "ERROR: foo:bar.comp.hlsl:2: 'a' : unknown variable"
|
||||
MessageType ParseGlslangOutput(const shaderc_util::string_piece& message,
|
||||
bool warnings_as_errors, bool suppress_warnings,
|
||||
shaderc_util::string_piece* source_name,
|
||||
shaderc_util::string_piece* line_number,
|
||||
shaderc_util::string_piece* rest);
|
||||
|
||||
// Filters error_messages received from glslang, and outputs, to error_stream,
|
||||
// any that are not ignored in a clang like format. If the warnings_as_errors
|
||||
// boolean is set, then all warnings will be treated as errors. If the
|
||||
// suppress_warnings boolean is set then any warning messages are ignored. This
|
||||
// takes precedence over warnings_as_errors. Increments total_warnings and
|
||||
// total_errors based on the message types.
|
||||
// Returns true if no new errors were found when parsing the messages.
|
||||
// "<command line>" will substitute "-1" appearing at the string name/number
|
||||
// segment.
|
||||
bool PrintFilteredErrors(const shaderc_util::string_piece& file_name,
|
||||
std::ostream* error_stream, bool warnings_as_errors,
|
||||
bool suppress_warnings, const char* error_list,
|
||||
size_t* total_warnings, size_t* total_errors);
|
||||
|
||||
// Outputs, to error_stream, the number of warnings and errors if there are
|
||||
// any.
|
||||
void OutputMessages(std::ostream* error_stream, size_t total_warnings,
|
||||
size_t total_errors);
|
||||
|
||||
} // namespace glslc
|
||||
|
||||
#endif // LIBSHADERC_UTIL_SRC_MESSAGE_H_
|
||||
107
3rdparty/shaderc/libshaderc_util/include/libshaderc_util/mutex.h
vendored
Normal file
107
3rdparty/shaderc/libshaderc_util/include/libshaderc_util/mutex.h
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
// Copyright 2015 The Shaderc Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBSHADERC_UTIL_INC_MUTEX_H
|
||||
#define LIBSHADERC_UTIL_INC_MUTEX_H
|
||||
|
||||
// shaderc_util::mutex will be defined and specialized
|
||||
// depending on the platform that is being compiled.
|
||||
// It is more or less conformant to the C++11 specification of std::mutex.
|
||||
// However it does not implement try_lock.
|
||||
|
||||
#ifdef _WIN32
|
||||
// windows.h #defines min and max if we don't define this.
|
||||
// this means things like std::min and std::max break
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
namespace shaderc_util {
|
||||
|
||||
// As the name suggests, this mutex class is for running on windows.
|
||||
// It conforms to the c++11 mutex implementation, and should be a
|
||||
// drop in replacement.
|
||||
class windows_mutex {
|
||||
public:
|
||||
using native_handle_type = HANDLE;
|
||||
|
||||
windows_mutex() { mutex_ = CreateMutex(nullptr, false, nullptr); }
|
||||
|
||||
~windows_mutex() {
|
||||
if (mutex_ != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(mutex_);
|
||||
}
|
||||
}
|
||||
|
||||
windows_mutex(const windows_mutex&) = delete;
|
||||
windows_mutex& operator=(const windows_mutex&) = delete;
|
||||
|
||||
// Locks this mutex, waiting until the mutex is unlocked if it is not already.
|
||||
// It is not valid to lock a mutex that has already been locked.
|
||||
void lock() { WaitForSingleObject(mutex_, INFINITE); }
|
||||
|
||||
// Unlocks this mutex. It is invalid to unlock a mutex that this thread
|
||||
// has not already locked.
|
||||
void unlock() { ReleaseMutex(mutex_); }
|
||||
|
||||
// Returns the native handle for this mutex. In this case a HANDLE object.
|
||||
native_handle_type native_handle() { return mutex_; }
|
||||
|
||||
private:
|
||||
HANDLE mutex_;
|
||||
};
|
||||
|
||||
using mutex = windows_mutex;
|
||||
}
|
||||
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#include <memory>
|
||||
namespace shaderc_util {
|
||||
|
||||
// As the name suggests, this mutex class is for running with pthreads.
|
||||
// It conforms to the c++11 mutex implementation, and should be a
|
||||
// drop in replacement.
|
||||
class posix_mutex {
|
||||
public:
|
||||
using native_handle_type = pthread_mutex_t*;
|
||||
|
||||
posix_mutex() { pthread_mutex_init(&mutex_, nullptr); }
|
||||
|
||||
~posix_mutex() { pthread_mutex_destroy(&mutex_); }
|
||||
|
||||
posix_mutex(const posix_mutex&) = delete;
|
||||
posix_mutex& operator=(const posix_mutex&) = delete;
|
||||
|
||||
// Locks this mutex, waiting until the mutex is unlocked if it is not already.
|
||||
// It is not valid to lock a mutex that has already been locked.
|
||||
void lock() { pthread_mutex_lock(&mutex_); }
|
||||
|
||||
// Unlocks this mutex. It is invalid to unlock a mutex that this thread
|
||||
// has not already locked.
|
||||
void unlock() { pthread_mutex_unlock(&mutex_); }
|
||||
|
||||
// Returns the native handle for this mutex. In this case a pthread_mutex_t*.
|
||||
native_handle_type native_handle() { return &mutex_; }
|
||||
|
||||
private:
|
||||
pthread_mutex_t mutex_;
|
||||
};
|
||||
|
||||
using mutex = posix_mutex;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // LIBSHADERC_UTIL_INC_MUTEX_H
|
||||
30
3rdparty/shaderc/libshaderc_util/include/libshaderc_util/resources.h
vendored
Normal file
30
3rdparty/shaderc/libshaderc_util/include/libshaderc_util/resources.h
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
// Copyright 2015 The Shaderc Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBSHADERC_UTIL_RESOURCES_H_
|
||||
#define LIBSHADERC_UTIL_RESOURCES_H_
|
||||
|
||||
// We want TBuiltInResource
|
||||
#include "glslang/Include/ResourceLimits.h"
|
||||
|
||||
namespace shaderc_util {
|
||||
|
||||
using TBuiltInResource = ::TBuiltInResource;
|
||||
|
||||
// A set of suitable defaults.
|
||||
extern const TBuiltInResource kDefaultTBuiltInResource;
|
||||
|
||||
} // namespace shaderc_util
|
||||
|
||||
#endif // LIBSHADERC_UTIL_RESOURCES_H_
|
||||
143
3rdparty/shaderc/libshaderc_util/include/libshaderc_util/resources.inc
vendored
Normal file
143
3rdparty/shaderc/libshaderc_util/include/libshaderc_util/resources.inc
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
// Copyright 2016 The Shaderc Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// These are the resource limits in a glslang::TBuiltInResource.
|
||||
// The first field is the string name to be used in a configuration setting.
|
||||
// The second field is the fieldname in TBuiltInResource.
|
||||
// The third field is the enum name fragment for shaderc_limit.
|
||||
//
|
||||
// TODO(dneto): Consider using a single list of names, but use a Python script
|
||||
// to generate *this* file. The original data file would have the first field,
|
||||
// then generate the second field by lowering the case of the first letter, and
|
||||
// generate the third field by taking the second field, and converting a
|
||||
// lower-to-upper case transition into an underscore with lower-case.
|
||||
RESOURCE(MaxLights,maxLights,max_lights)
|
||||
RESOURCE(MaxClipPlanes,maxClipPlanes,max_clip_planes)
|
||||
RESOURCE(MaxTextureUnits,maxTextureUnits,max_texture_units)
|
||||
RESOURCE(MaxTextureCoords,maxTextureCoords,max_texture_coords)
|
||||
RESOURCE(MaxVertexAttribs,maxVertexAttribs,max_vertex_attribs)
|
||||
RESOURCE(MaxVertexUniformComponents,maxVertexUniformComponents,max_vertex_uniform_components)
|
||||
RESOURCE(MaxVaryingFloats,maxVaryingFloats,max_varying_floats)
|
||||
RESOURCE(MaxVertexTextureImageUnits,maxVertexTextureImageUnits,max_vertex_texture_image_units)
|
||||
RESOURCE(MaxCombinedTextureImageUnits,maxCombinedTextureImageUnits,max_combined_texture_image_units)
|
||||
RESOURCE(MaxTextureImageUnits,maxTextureImageUnits,max_texture_image_units)
|
||||
RESOURCE(MaxFragmentUniformComponents,maxFragmentUniformComponents,max_fragment_uniform_components)
|
||||
RESOURCE(MaxDrawBuffers,maxDrawBuffers,max_draw_buffers)
|
||||
RESOURCE(MaxVertexUniformVectors,maxVertexUniformVectors,max_vertex_uniform_vectors)
|
||||
RESOURCE(MaxVaryingVectors,maxVaryingVectors,max_varying_vectors)
|
||||
RESOURCE(MaxFragmentUniformVectors,maxFragmentUniformVectors,max_fragment_uniform_vectors)
|
||||
RESOURCE(MaxVertexOutputVectors,maxVertexOutputVectors,max_vertex_output_vectors)
|
||||
RESOURCE(MaxFragmentInputVectors,maxFragmentInputVectors,max_fragment_input_vectors)
|
||||
RESOURCE(MinProgramTexelOffset,minProgramTexelOffset,min_program_texel_offset)
|
||||
RESOURCE(MaxProgramTexelOffset,maxProgramTexelOffset,max_program_texel_offset)
|
||||
RESOURCE(MaxClipDistances,maxClipDistances,max_clip_distances)
|
||||
RESOURCE(MaxComputeWorkGroupCountX,maxComputeWorkGroupCountX,max_compute_work_group_count_x)
|
||||
RESOURCE(MaxComputeWorkGroupCountY,maxComputeWorkGroupCountY,max_compute_work_group_count_y)
|
||||
RESOURCE(MaxComputeWorkGroupCountZ,maxComputeWorkGroupCountZ,max_compute_work_group_count_z)
|
||||
RESOURCE(MaxComputeWorkGroupSizeX,maxComputeWorkGroupSizeX,max_compute_work_group_size_x)
|
||||
RESOURCE(MaxComputeWorkGroupSizeY,maxComputeWorkGroupSizeY,max_compute_work_group_size_y)
|
||||
RESOURCE(MaxComputeWorkGroupSizeZ,maxComputeWorkGroupSizeZ,max_compute_work_group_size_z)
|
||||
RESOURCE(MaxComputeUniformComponents,maxComputeUniformComponents,max_compute_uniform_components)
|
||||
RESOURCE(MaxComputeTextureImageUnits,maxComputeTextureImageUnits,max_compute_texture_image_units)
|
||||
RESOURCE(MaxComputeImageUniforms,maxComputeImageUniforms,max_compute_image_uniforms)
|
||||
RESOURCE(MaxComputeAtomicCounters,maxComputeAtomicCounters,max_compute_atomic_counters)
|
||||
RESOURCE(MaxComputeAtomicCounterBuffers,maxComputeAtomicCounterBuffers,max_compute_atomic_counter_buffers)
|
||||
RESOURCE(MaxVaryingComponents,maxVaryingComponents,max_varying_components)
|
||||
RESOURCE(MaxVertexOutputComponents,maxVertexOutputComponents,max_vertex_output_components)
|
||||
RESOURCE(MaxGeometryInputComponents,maxGeometryInputComponents,max_geometry_input_components)
|
||||
RESOURCE(MaxGeometryOutputComponents,maxGeometryOutputComponents,max_geometry_output_components)
|
||||
RESOURCE(MaxFragmentInputComponents,maxFragmentInputComponents,max_fragment_input_components)
|
||||
RESOURCE(MaxImageUnits,maxImageUnits,max_image_units)
|
||||
RESOURCE(MaxCombinedImageUnitsAndFragmentOutputs,maxCombinedImageUnitsAndFragmentOutputs,max_combined_image_units_and_fragment_outputs)
|
||||
RESOURCE(MaxCombinedShaderOutputResources,maxCombinedShaderOutputResources,max_combined_shader_output_resources)
|
||||
RESOURCE(MaxImageSamples,maxImageSamples,max_image_samples)
|
||||
RESOURCE(MaxVertexImageUniforms,maxVertexImageUniforms,max_vertex_image_uniforms)
|
||||
RESOURCE(MaxTessControlImageUniforms,maxTessControlImageUniforms,max_tess_control_image_uniforms)
|
||||
RESOURCE(MaxTessEvaluationImageUniforms,maxTessEvaluationImageUniforms,max_tess_evaluation_image_uniforms)
|
||||
RESOURCE(MaxGeometryImageUniforms,maxGeometryImageUniforms,max_geometry_image_uniforms)
|
||||
RESOURCE(MaxFragmentImageUniforms,maxFragmentImageUniforms,max_fragment_image_uniforms)
|
||||
RESOURCE(MaxCombinedImageUniforms,maxCombinedImageUniforms,max_combined_image_uniforms)
|
||||
RESOURCE(MaxGeometryTextureImageUnits,maxGeometryTextureImageUnits,max_geometry_texture_image_units)
|
||||
RESOURCE(MaxGeometryOutputVertices,maxGeometryOutputVertices,max_geometry_output_vertices)
|
||||
RESOURCE(MaxGeometryTotalOutputComponents,maxGeometryTotalOutputComponents,max_geometry_total_output_components)
|
||||
RESOURCE(MaxGeometryUniformComponents,maxGeometryUniformComponents,max_geometry_uniform_components)
|
||||
RESOURCE(MaxGeometryVaryingComponents,maxGeometryVaryingComponents,max_geometry_varying_components)
|
||||
RESOURCE(MaxTessControlInputComponents,maxTessControlInputComponents,max_tess_control_input_components)
|
||||
RESOURCE(MaxTessControlOutputComponents,maxTessControlOutputComponents,max_tess_control_output_components)
|
||||
RESOURCE(MaxTessControlTextureImageUnits,maxTessControlTextureImageUnits,max_tess_control_texture_image_units)
|
||||
RESOURCE(MaxTessControlUniformComponents,maxTessControlUniformComponents,max_tess_control_uniform_components)
|
||||
RESOURCE(MaxTessControlTotalOutputComponents,maxTessControlTotalOutputComponents,max_tess_control_total_output_components)
|
||||
RESOURCE(MaxTessEvaluationInputComponents,maxTessEvaluationInputComponents,max_tess_evaluation_input_components)
|
||||
RESOURCE(MaxTessEvaluationOutputComponents,maxTessEvaluationOutputComponents,max_tess_evaluation_output_components)
|
||||
RESOURCE(MaxTessEvaluationTextureImageUnits,maxTessEvaluationTextureImageUnits,max_tess_evaluation_texture_image_units)
|
||||
RESOURCE(MaxTessEvaluationUniformComponents,maxTessEvaluationUniformComponents,max_tess_evaluation_uniform_components)
|
||||
RESOURCE(MaxTessPatchComponents,maxTessPatchComponents,max_tess_patch_components)
|
||||
RESOURCE(MaxPatchVertices,maxPatchVertices,max_patch_vertices)
|
||||
RESOURCE(MaxTessGenLevel,maxTessGenLevel,max_tess_gen_level)
|
||||
RESOURCE(MaxViewports,maxViewports,max_viewports)
|
||||
RESOURCE(MaxVertexAtomicCounters,maxVertexAtomicCounters,max_vertex_atomic_counters)
|
||||
RESOURCE(MaxTessControlAtomicCounters,maxTessControlAtomicCounters,max_tess_control_atomic_counters)
|
||||
RESOURCE(MaxTessEvaluationAtomicCounters,maxTessEvaluationAtomicCounters,max_tess_evaluation_atomic_counters)
|
||||
RESOURCE(MaxGeometryAtomicCounters,maxGeometryAtomicCounters,max_geometry_atomic_counters)
|
||||
RESOURCE(MaxFragmentAtomicCounters,maxFragmentAtomicCounters,max_fragment_atomic_counters)
|
||||
RESOURCE(MaxCombinedAtomicCounters,maxCombinedAtomicCounters,max_combined_atomic_counters)
|
||||
RESOURCE(MaxAtomicCounterBindings,maxAtomicCounterBindings,max_atomic_counter_bindings)
|
||||
RESOURCE(MaxVertexAtomicCounterBuffers,maxVertexAtomicCounterBuffers,max_vertex_atomic_counter_buffers)
|
||||
RESOURCE(MaxTessControlAtomicCounterBuffers,maxTessControlAtomicCounterBuffers,max_tess_control_atomic_counter_buffers)
|
||||
RESOURCE(MaxTessEvaluationAtomicCounterBuffers,maxTessEvaluationAtomicCounterBuffers,max_tess_evaluation_atomic_counter_buffers)
|
||||
RESOURCE(MaxGeometryAtomicCounterBuffers,maxGeometryAtomicCounterBuffers,max_geometry_atomic_counter_buffers)
|
||||
RESOURCE(MaxFragmentAtomicCounterBuffers,maxFragmentAtomicCounterBuffers,max_fragment_atomic_counter_buffers)
|
||||
RESOURCE(MaxCombinedAtomicCounterBuffers,maxCombinedAtomicCounterBuffers,max_combined_atomic_counter_buffers)
|
||||
RESOURCE(MaxAtomicCounterBufferSize,maxAtomicCounterBufferSize,max_atomic_counter_buffer_size)
|
||||
RESOURCE(MaxTransformFeedbackBuffers,maxTransformFeedbackBuffers,max_transform_feedback_buffers)
|
||||
RESOURCE(MaxTransformFeedbackInterleavedComponents,maxTransformFeedbackInterleavedComponents,max_transform_feedback_interleaved_components)
|
||||
RESOURCE(MaxCullDistances,maxCullDistances,max_cull_distances)
|
||||
RESOURCE(MaxCombinedClipAndCullDistances,maxCombinedClipAndCullDistances,max_combined_clip_and_cull_distances)
|
||||
RESOURCE(MaxSamples,maxSamples,max_samples)
|
||||
RESOURCE(MaxMeshOutputVerticesNV, maxMeshOutputVerticesNV,
|
||||
max_mesh_output_vertices_nv)
|
||||
RESOURCE(MaxMeshOutputPrimitivesNV, maxMeshOutputPrimitivesNV,
|
||||
max_mesh_output_primitives_nv)
|
||||
RESOURCE(MaxMeshWorkGroupSizeX_NV, maxMeshWorkGroupSizeX_NV,
|
||||
max_mesh_work_group_size_x_nv)
|
||||
RESOURCE(MaxMeshWorkGroupSizeY_NV, maxMeshWorkGroupSizeY_NV,
|
||||
max_mesh_work_group_size_y_nv)
|
||||
RESOURCE(MaxMeshWorkGroupSizeZ_NV, maxMeshWorkGroupSizeZ_NV,
|
||||
max_mesh_work_group_size_z_nv)
|
||||
RESOURCE(MaxTaskWorkGroupSizeX_NV, maxTaskWorkGroupSizeX_NV,
|
||||
max_task_work_group_size_x_nv)
|
||||
RESOURCE(MaxTaskWorkGroupSizeY_NV, maxTaskWorkGroupSizeY_NV,
|
||||
max_task_work_group_size_y_nv)
|
||||
RESOURCE(MaxTaskWorkGroupSizeZ_NV, maxTaskWorkGroupSizeZ_NV,
|
||||
max_task_work_group_size_z_nv)
|
||||
RESOURCE(MaxMeshViewCountNV, maxMeshViewCountNV, max_mesh_view_count_nv)
|
||||
RESOURCE(MaxMeshOutputVerticesEXT, maxMeshOutputVerticesEXT,
|
||||
max_mesh_output_vertices_ext)
|
||||
RESOURCE(MaxMeshOutputPrimitivesEXT, maxMeshOutputPrimitivesEXT,
|
||||
max_mesh_output_primitives_ext)
|
||||
RESOURCE(MaxMeshWorkGroupSizeX_EXT, maxMeshWorkGroupSizeX_EXT,
|
||||
max_mesh_work_group_size_x_ext)
|
||||
RESOURCE(MaxMeshWorkGroupSizeY_EXT, maxMeshWorkGroupSizeY_EXT,
|
||||
max_mesh_work_group_size_y_ext)
|
||||
RESOURCE(MaxMeshWorkGroupSizeZ_EXT, maxMeshWorkGroupSizeZ_EXT,
|
||||
max_mesh_work_group_size_z_ext)
|
||||
RESOURCE(MaxTaskWorkGroupSizeX_EXT, maxTaskWorkGroupSizeX_EXT,
|
||||
max_task_work_group_size_x_ext)
|
||||
RESOURCE(MaxTaskWorkGroupSizeY_EXT, maxTaskWorkGroupSizeY_EXT,
|
||||
max_task_work_group_size_y_ext)
|
||||
RESOURCE(MaxTaskWorkGroupSizeZ_EXT, maxTaskWorkGroupSizeZ_EXT,
|
||||
max_task_work_group_size_z_ext)
|
||||
RESOURCE(MaxMeshViewCountEXT, maxMeshViewCountEXT, max_mesh_view_count_ext)
|
||||
RESOURCE(MaxDualSourceDrawBuffersEXT, maxDualSourceDrawBuffersEXT,
|
||||
max_dual_source_draw_buffers_ext)
|
||||
36
3rdparty/shaderc/libshaderc_util/include/libshaderc_util/shader_stage.h
vendored
Normal file
36
3rdparty/shaderc/libshaderc_util/include/libshaderc_util/shader_stage.h
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
// Copyright 2015 The Shaderc Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBSHADERC_UTIL_SHADER_STAGE_H_
|
||||
#define LIBSHADERC_UTIL_SHADER_STAGE_H_
|
||||
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "glslang/Public/ShaderLang.h"
|
||||
|
||||
#include "libshaderc_util/string_piece.h"
|
||||
|
||||
namespace shaderc_util {
|
||||
|
||||
// Given a string representing a stage, returns the glslang EShLanguage for it.
|
||||
// If the stage string is not recognized, returns EShLangCount.
|
||||
EShLanguage MapStageNameToLanguage(
|
||||
const shaderc_util::string_piece& stage_name);
|
||||
|
||||
} // namespace shaderc_util
|
||||
|
||||
#endif // LIBSHADERC_UTIL_SHADER_STAGE_H_
|
||||
68
3rdparty/shaderc/libshaderc_util/include/libshaderc_util/spirv_tools_wrapper.h
vendored
Normal file
68
3rdparty/shaderc/libshaderc_util/include/libshaderc_util/spirv_tools_wrapper.h
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
// Copyright 2016 The Shaderc Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBSHADERC_UTIL_INC_SPIRV_TOOLS_WRAPPER_H
|
||||
#define LIBSHADERC_UTIL_INC_SPIRV_TOOLS_WRAPPER_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "spirv-tools/libspirv.hpp"
|
||||
|
||||
#include "libshaderc_util/compiler.h"
|
||||
#include "libshaderc_util/string_piece.h"
|
||||
|
||||
namespace shaderc_util {
|
||||
// Assembles the given assembly. On success, returns true, writes the assembled
|
||||
// binary to *binary, and clears *errors. Otherwise, writes the error message
|
||||
// into *errors.
|
||||
bool SpirvToolsAssemble(Compiler::TargetEnv env,
|
||||
Compiler::TargetEnvVersion version,
|
||||
const string_piece assembly, spv_binary* binary,
|
||||
std::string* errors);
|
||||
|
||||
// Disassembles the given binary. Returns true and writes the disassembled text
|
||||
// to *text_or_error if successful. Otherwise, writes the error message to
|
||||
// *text_or_error.
|
||||
bool SpirvToolsDisassemble(Compiler::TargetEnv env,
|
||||
Compiler::TargetEnvVersion version,
|
||||
const std::vector<uint32_t>& binary,
|
||||
std::string* text_or_error);
|
||||
|
||||
// The ids of a list of supported optimization passes.
|
||||
enum class PassId {
|
||||
// SPIRV-Tools standard recipes
|
||||
kLegalizationPasses,
|
||||
kPerformancePasses,
|
||||
kSizePasses,
|
||||
|
||||
// SPIRV-Tools specific passes
|
||||
kNullPass,
|
||||
kStripDebugInfo,
|
||||
kCompactIds,
|
||||
};
|
||||
|
||||
// Optimizes the given binary. Passes are registered in the exact order as shown
|
||||
// in enabled_passes, without de-duplication. Returns true and writes the
|
||||
// optimized binary back to *binary if successful. Otherwise, writes errors to
|
||||
// *errors and the content of binary may be in an invalid state.
|
||||
bool SpirvToolsOptimize(Compiler::TargetEnv env,
|
||||
Compiler::TargetEnvVersion version,
|
||||
const std::vector<PassId>& enabled_passes,
|
||||
spvtools::OptimizerOptions& optimizer_options,
|
||||
std::vector<uint32_t>* binary, std::string* errors);
|
||||
|
||||
} // namespace shaderc_util
|
||||
|
||||
#endif // LIBSHADERC_UTIL_INC_SPIRV_TOOLS_WRAPPER_H
|
||||
357
3rdparty/shaderc/libshaderc_util/include/libshaderc_util/string_piece.h
vendored
Normal file
357
3rdparty/shaderc/libshaderc_util/include/libshaderc_util/string_piece.h
vendored
Normal file
@@ -0,0 +1,357 @@
|
||||
// Copyright 2015 The Shaderc Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBSHADERC_UTIL_STRING_PIECE_H_
|
||||
#define LIBSHADERC_UTIL_STRING_PIECE_H_
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <ostream>
|
||||
#include <vector>
|
||||
|
||||
namespace shaderc_util {
|
||||
// Provides a read-only view into a string (cstring or std::string).
|
||||
// This must be created after the string in question, and cannot
|
||||
// outlive the memory of the string in question.
|
||||
// Any operations that may modify the location or size of the
|
||||
// original data render the associated string_piece invalid.
|
||||
|
||||
class string_piece {
|
||||
public:
|
||||
typedef const char* iterator;
|
||||
static const size_t npos = -1;
|
||||
|
||||
string_piece() {}
|
||||
|
||||
string_piece(const char* begin, const char* end) : begin_(begin), end_(end) {
|
||||
assert((begin == nullptr) == (end == nullptr) &&
|
||||
"either both begin and end must be nullptr or neither must be");
|
||||
}
|
||||
|
||||
string_piece(const char* string) : begin_(string), end_(string) {
|
||||
if (string) {
|
||||
end_ += strlen(string);
|
||||
}
|
||||
}
|
||||
|
||||
string_piece(const std::string& str) {
|
||||
if (!str.empty()) {
|
||||
begin_ = &(str.front());
|
||||
end_ = &(str.back()) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
string_piece(const string_piece& other) {
|
||||
begin_ = other.begin_;
|
||||
end_ = other.end_;
|
||||
}
|
||||
|
||||
string_piece& operator=(const string_piece& other) = default;
|
||||
|
||||
// Clears the string_piece removing any reference to the original string.
|
||||
void clear() {
|
||||
begin_ = nullptr;
|
||||
end_ = nullptr;
|
||||
}
|
||||
|
||||
// Returns a pointer to the data contained in the underlying string.
|
||||
// If there is no underlying string, returns a nullptr.
|
||||
const char* data() const { return begin_; }
|
||||
|
||||
// Returns an std::string copy of the internal data.
|
||||
std::string str() const { return std::string(begin_, end_); }
|
||||
|
||||
// Returns a string_piece that points to a substring in the original string.
|
||||
string_piece substr(size_t pos, size_t len = npos) const {
|
||||
assert(len == npos || pos + len <= size());
|
||||
return string_piece(begin_ + pos, len == npos ? end_ : begin_ + pos + len);
|
||||
}
|
||||
|
||||
// Takes any function object predicate that takes a char and returns a
|
||||
// boolean.
|
||||
// Returns the index of the first element that does not return true for the
|
||||
// predicate.
|
||||
// Returns string_piece::npos if all elements match.
|
||||
template <typename T>
|
||||
size_t find_first_not_matching(T callee) {
|
||||
for (auto it = begin_; it != end_; ++it) {
|
||||
if (!callee(*it)) {
|
||||
return it - begin_;
|
||||
}
|
||||
}
|
||||
return npos;
|
||||
}
|
||||
|
||||
// Returns the index of the first character that does not match any character
|
||||
// in the input string_piece.
|
||||
// The search only includes characters at or after position pos.
|
||||
// Returns string_piece::npos if all match.
|
||||
size_t find_first_not_of(const string_piece& to_search,
|
||||
size_t pos = 0) const {
|
||||
if (pos >= size()) {
|
||||
return npos;
|
||||
}
|
||||
for (auto it = begin_ + pos; it != end_; ++it) {
|
||||
if (to_search.find_first_of(*it) == npos) {
|
||||
return it - begin_;
|
||||
}
|
||||
}
|
||||
return npos;
|
||||
}
|
||||
|
||||
// Returns find_first_not_of(str, pos) where str is a string_piece
|
||||
// containing only to_search.
|
||||
size_t find_first_not_of(char to_search, size_t pos = 0) const {
|
||||
return find_first_not_of(string_piece(&to_search, &to_search + 1), pos);
|
||||
}
|
||||
|
||||
// Returns the index of the first character that matches any character in the
|
||||
// input string_piece.
|
||||
// The search only includes characters at or after position pos.
|
||||
// Returns string_piece::npos if there is no match.
|
||||
size_t find_first_of(const string_piece& to_search, size_t pos = 0) const {
|
||||
if (pos >= size()) {
|
||||
return npos;
|
||||
}
|
||||
for (auto it = begin_ + pos; it != end_; ++it) {
|
||||
for (char c : to_search) {
|
||||
if (c == *it) {
|
||||
return it - begin_;
|
||||
}
|
||||
}
|
||||
}
|
||||
return npos;
|
||||
}
|
||||
|
||||
// Returns find_first_of(str, pos) where str is a string_piece
|
||||
// containing only to_search.
|
||||
size_t find_first_of(char to_search, size_t pos = 0) const {
|
||||
return find_first_of(string_piece(&to_search, &to_search + 1), pos);
|
||||
}
|
||||
|
||||
// Returns the index of the last character that matches any character in the
|
||||
// input string_piece.
|
||||
// The search only includes characters at or before position pos.
|
||||
// Returns string_piece::npos if there is no match.
|
||||
size_t find_last_of(const string_piece& to_search, size_t pos = npos) const {
|
||||
if (empty()) return npos;
|
||||
if (pos >= size()) {
|
||||
pos = size();
|
||||
}
|
||||
auto it = begin_ + pos + 1;
|
||||
do {
|
||||
--it;
|
||||
if (to_search.find_first_of(*it) != npos) {
|
||||
return it - begin_;
|
||||
}
|
||||
} while (it != begin_);
|
||||
return npos;
|
||||
}
|
||||
|
||||
// Returns find_last_of(str, pos) where str is a string_piece
|
||||
// containing only to_search.
|
||||
size_t find_last_of(char to_search, size_t pos = npos) const {
|
||||
return find_last_of(string_piece(&to_search, &to_search + 1), pos);
|
||||
}
|
||||
|
||||
// Returns the index of the last character that does not match any character
|
||||
// in the input string_piece.
|
||||
// The search only includes characters at or before position pos.
|
||||
// Returns string_piece::npos if there is no match.
|
||||
size_t find_last_not_of(const string_piece& to_search,
|
||||
size_t pos = npos) const {
|
||||
if (empty()) return npos;
|
||||
if (pos >= size()) {
|
||||
pos = size();
|
||||
}
|
||||
auto it = begin_ + pos + 1;
|
||||
do {
|
||||
--it;
|
||||
if (to_search.find_first_of(*it) == npos) {
|
||||
return it - begin_;
|
||||
}
|
||||
} while (it != begin_);
|
||||
return npos;
|
||||
}
|
||||
|
||||
// Returns find_last_not_of(str, pos) where str is a string_piece
|
||||
// containing only to_search.
|
||||
size_t find_last_not_of(char to_search, size_t pos = 0) const {
|
||||
return find_last_not_of(string_piece(&to_search, &to_search + 1), pos);
|
||||
}
|
||||
|
||||
// Continuously removes characters appearing in chars_to_strip from the left.
|
||||
string_piece lstrip(const string_piece& chars_to_strip) const {
|
||||
iterator begin = begin_;
|
||||
for (; begin < end_; ++begin)
|
||||
if (chars_to_strip.find_first_of(*begin) == npos) break;
|
||||
if (begin >= end_) return string_piece();
|
||||
return string_piece(begin, end_);
|
||||
}
|
||||
|
||||
// Continuously removes characters appearing in chars_to_strip from the right.
|
||||
string_piece rstrip(const string_piece& chars_to_strip) const {
|
||||
iterator end = end_;
|
||||
for (; begin_ < end; --end)
|
||||
if (chars_to_strip.find_first_of(*(end - 1)) == npos) break;
|
||||
if (begin_ >= end) return string_piece();
|
||||
return string_piece(begin_, end);
|
||||
}
|
||||
|
||||
// Continuously removes characters appearing in chars_to_strip from both
|
||||
// sides.
|
||||
string_piece strip(const string_piece& chars_to_strip) const {
|
||||
return lstrip(chars_to_strip).rstrip(chars_to_strip);
|
||||
}
|
||||
|
||||
string_piece strip_whitespace() const { return strip(" \t\n\r\f\v"); }
|
||||
|
||||
// Returns the character at index i in the string_piece.
|
||||
const char& operator[](size_t i) const { return *(begin_ + i); }
|
||||
|
||||
// Standard comparison operator.
|
||||
bool operator==(const string_piece& other) const {
|
||||
// Either end_ and _begin_ are nullptr or neither of them are.
|
||||
assert(((end_ == nullptr) == (begin_ == nullptr)));
|
||||
assert(((other.end_ == nullptr) == (other.begin_ == nullptr)));
|
||||
if (size() != other.size()) {
|
||||
return false;
|
||||
}
|
||||
return (memcmp(begin_, other.begin_, end_ - begin_) == 0);
|
||||
}
|
||||
|
||||
bool operator!=(const string_piece& other) const {
|
||||
return !operator==(other);
|
||||
}
|
||||
|
||||
// Returns an iterator to the first element.
|
||||
iterator begin() const { return begin_; }
|
||||
|
||||
// Returns an iterator to one past the last element.
|
||||
iterator end() const { return end_; }
|
||||
|
||||
const char& front() const {
|
||||
assert(!empty());
|
||||
return *begin_;
|
||||
}
|
||||
|
||||
const char& back() const {
|
||||
assert(!empty());
|
||||
return *(end_ - 1);
|
||||
}
|
||||
|
||||
// Returns true is this string_piece starts with the same
|
||||
// characters as other.
|
||||
bool starts_with(const string_piece& other) const {
|
||||
const char* iter = begin_;
|
||||
const char* other_iter = other.begin();
|
||||
while (iter != end_ && other_iter != other.end()) {
|
||||
if (*iter++ != *other_iter++) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return other_iter == other.end();
|
||||
}
|
||||
|
||||
// Returns the index of the start of the first substring that matches
|
||||
// the input string_piece.
|
||||
// The search only includes substrings starting at or after position pos.
|
||||
// Returns npos if the string cannot be found.
|
||||
size_t find(const string_piece& substr, size_t pos = 0) const {
|
||||
if (empty()) return npos;
|
||||
if (pos >= size()) return npos;
|
||||
if (substr.empty()) return 0;
|
||||
for (auto it = begin_ + pos;
|
||||
end() - it >= static_cast<decltype(end() - it)>(substr.size()); ++it) {
|
||||
if (string_piece(it, end()).starts_with(substr)) return it - begin_;
|
||||
}
|
||||
return npos;
|
||||
}
|
||||
|
||||
// Returns the index of the start of the first character that matches
|
||||
// the input character.
|
||||
// The search only includes substrings starting at or after position pos.
|
||||
// Returns npos if the character cannot be found.
|
||||
size_t find(char character, size_t pos = 0) const {
|
||||
return find_first_of(character, pos);
|
||||
}
|
||||
|
||||
// Returns true if the string_piece is empty.
|
||||
bool empty() const { return begin_ == end_; }
|
||||
|
||||
// Returns the number of characters in the string_piece.
|
||||
size_t size() const { return end_ - begin_; }
|
||||
|
||||
// Returns a vector of string_pieces representing delimiter delimited
|
||||
// fields found. If the keep_delimiter parameter is true, then each
|
||||
// delimiter character is kept with the string to its left.
|
||||
std::vector<string_piece> get_fields(char delimiter,
|
||||
bool keep_delimiter = false) const {
|
||||
std::vector<string_piece> fields;
|
||||
size_t first = 0;
|
||||
size_t field_break = find_first_of(delimiter);
|
||||
while (field_break != npos) {
|
||||
fields.push_back(substr(first, field_break - first + keep_delimiter));
|
||||
first = field_break + 1;
|
||||
field_break = find_first_of(delimiter, first);
|
||||
}
|
||||
if (size() - first > 0) {
|
||||
fields.push_back(substr(first, size() - first));
|
||||
}
|
||||
return fields;
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const string_piece& piece);
|
||||
|
||||
private:
|
||||
// It is expected that begin_ and end_ will both be null or
|
||||
// they will both point to valid pieces of memory, but it is invalid
|
||||
// to have one of them being nullptr and the other not.
|
||||
string_piece::iterator begin_ = nullptr;
|
||||
string_piece::iterator end_ = nullptr;
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const string_piece& piece) {
|
||||
// Either end_ and _begin_ are nullptr or neither of them are.
|
||||
assert(((piece.end_ == nullptr) == (piece.begin_ == nullptr)));
|
||||
if (piece.end_ != piece.begin_) {
|
||||
os.write(piece.begin_, piece.end_ - piece.begin_);
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
inline bool operator==(const char* first, const string_piece second) {
|
||||
return second == string_piece(first);
|
||||
}
|
||||
|
||||
inline bool operator!=(const char* first, const string_piece second) {
|
||||
return !operator==(first, second);
|
||||
}
|
||||
}
|
||||
|
||||
namespace std {
|
||||
template <>
|
||||
struct hash<shaderc_util::string_piece> {
|
||||
size_t operator()(const shaderc_util::string_piece& piece) const {
|
||||
// djb2 algorithm.
|
||||
size_t hash = 5381;
|
||||
for (char c : piece) {
|
||||
hash = ((hash << 5) + hash) + c;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // LIBSHADERC_UTIL_STRING_PIECE_H_
|
||||
32
3rdparty/shaderc/libshaderc_util/include/libshaderc_util/universal_unistd.h
vendored
Normal file
32
3rdparty/shaderc/libshaderc_util/include/libshaderc_util/universal_unistd.h
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
// Copyright 2015 The Shaderc Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBSHADERC_UTIL_UNIVERSAL_UNISTD_H_
|
||||
#define LIBSHADERC_UTIL_UNIVERSAL_UNISTD_H_
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#include <unistd.h>
|
||||
#else
|
||||
// Minimal set of <unistd> needed to compile on windows.
|
||||
|
||||
#include <io.h>
|
||||
#define access _access
|
||||
|
||||
// https://msdn.microsoft.com/en-us/library/1w06ktdy.aspx
|
||||
// Defines these constants.
|
||||
#define R_OK 4
|
||||
#define W_OK 2
|
||||
#endif //_MSC_VER
|
||||
|
||||
#endif // LIBSHADERC_UTIL_UNIVERSAL_UNISTD_H_
|
||||
61
3rdparty/shaderc/libshaderc_util/include/libshaderc_util/version_profile.h
vendored
Normal file
61
3rdparty/shaderc/libshaderc_util/include/libshaderc_util/version_profile.h
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
// Copyright 2015 The Shaderc Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBSHADERC_UTIL_INC_VERSION_PROFILE_H_
|
||||
#define LIBSHADERC_UTIL_INC_VERSION_PROFILE_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "glslang/MachineIndependent/Versions.h"
|
||||
|
||||
namespace shaderc_util {
|
||||
|
||||
// Returns true if the given version is an accepted GLSL (ES) version.
|
||||
inline bool IsKnownVersion(int version) {
|
||||
switch (version) {
|
||||
case 100:
|
||||
case 110:
|
||||
case 120:
|
||||
case 130:
|
||||
case 140:
|
||||
case 150:
|
||||
case 300:
|
||||
case 310:
|
||||
case 320:
|
||||
case 330:
|
||||
case 400:
|
||||
case 410:
|
||||
case 420:
|
||||
case 430:
|
||||
case 440:
|
||||
case 450:
|
||||
case 460:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Given a string version_profile containing both version and profile, decodes
|
||||
// it and puts the decoded version in version, decoded profile in profile.
|
||||
// Returns true if decoding is successful and version and profile are accepted.
|
||||
// This does not validate the version number against the profile. For example,
|
||||
// "460es" doesn't make sense (yet), but is still accepted.
|
||||
bool ParseVersionProfile(const std::string& version_profile, int* version,
|
||||
EProfile* profile);
|
||||
|
||||
} // namespace shaderc_util
|
||||
|
||||
#endif // LIBSHADERC_UTIL_INC_VERSION_PROFILE_H_
|
||||
62
3rdparty/shaderc/libshaderc_util/src/args.cc
vendored
Normal file
62
3rdparty/shaderc/libshaderc_util/src/args.cc
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
// Copyright 2019 The Shaderc Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "libshaderc_util/args.h"
|
||||
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
|
||||
namespace shaderc_util {
|
||||
|
||||
bool GetOptionArgument(int argc, char** argv, int* index,
|
||||
const std::string& option,
|
||||
string_piece* option_argument) {
|
||||
const string_piece arg = argv[*index];
|
||||
assert(arg.starts_with(option));
|
||||
if (arg.size() != option.size()) {
|
||||
*option_argument = arg.substr(option.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
if (option.back() == '=') {
|
||||
*option_argument = "";
|
||||
return true;
|
||||
}
|
||||
|
||||
if (++(*index) >= argc) return false;
|
||||
*option_argument = argv[*index];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParseUint32(const std::string& str, uint32_t* value) {
|
||||
std::istringstream iss(str);
|
||||
|
||||
iss >> std::setbase(0);
|
||||
iss >> *value;
|
||||
|
||||
// We should have read something.
|
||||
bool ok = !str.empty() && !iss.bad();
|
||||
// It should have been all the text.
|
||||
ok = ok && iss.eof();
|
||||
// It should have been in range.
|
||||
ok = ok && !iss.fail();
|
||||
|
||||
// Work around a bugs in various C++ standard libraries.
|
||||
// Count any negative number as an error, including "-0".
|
||||
ok = ok && (str[0] != '-');
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
} // namespace shaderc_util
|
||||
826
3rdparty/shaderc/libshaderc_util/src/compiler.cc
vendored
Normal file
826
3rdparty/shaderc/libshaderc_util/src/compiler.cc
vendored
Normal file
@@ -0,0 +1,826 @@
|
||||
// Copyright 2015 The Shaderc Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "libshaderc_util/compiler.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <thread>
|
||||
#include <tuple>
|
||||
|
||||
#include "SPIRV/GlslangToSpv.h"
|
||||
#include "libshaderc_util/format.h"
|
||||
#include "libshaderc_util/io_shaderc.h"
|
||||
#include "libshaderc_util/message.h"
|
||||
#include "libshaderc_util/resources.h"
|
||||
#include "libshaderc_util/shader_stage.h"
|
||||
#include "libshaderc_util/spirv_tools_wrapper.h"
|
||||
#include "libshaderc_util/string_piece.h"
|
||||
#include "libshaderc_util/version_profile.h"
|
||||
#include "spirv-tools/libspirv.hpp"
|
||||
|
||||
namespace {
|
||||
using shaderc_util::string_piece;
|
||||
|
||||
// For use with glslang parsing calls.
|
||||
const bool kNotForwardCompatible = false;
|
||||
|
||||
// Returns true if #line directive sets the line number for the next line in the
|
||||
// given version and profile.
|
||||
inline bool LineDirectiveIsForNextLine(int version, EProfile profile) {
|
||||
return profile == EEsProfile || version >= 330;
|
||||
}
|
||||
|
||||
// Returns a #line directive whose arguments are line and filename.
|
||||
inline std::string GetLineDirective(int line, const string_piece& filename) {
|
||||
return "#line " + std::to_string(line) + " \"" + filename.str() + "\"\n";
|
||||
}
|
||||
|
||||
// Given a canonicalized #line directive (starting exactly with "#line", using
|
||||
// single spaces to separate different components, and having an optional
|
||||
// newline at the end), returns the line number and string name/number. If no
|
||||
// string name/number is provided, the second element in the returned pair is an
|
||||
// empty string_piece. Behavior is undefined if the directive parameter is not a
|
||||
// canonicalized #line directive.
|
||||
std::pair<int, string_piece> DecodeLineDirective(string_piece directive) {
|
||||
const string_piece kLineDirective = "#line ";
|
||||
assert(directive.starts_with(kLineDirective));
|
||||
directive = directive.substr(kLineDirective.size());
|
||||
|
||||
const int line = std::atoi(directive.data());
|
||||
const size_t space_loc = directive.find_first_of(' ');
|
||||
if (space_loc == string_piece::npos) return std::make_pair(line, "");
|
||||
|
||||
directive = directive.substr(space_loc);
|
||||
directive = directive.strip("\" \n");
|
||||
return std::make_pair(line, directive);
|
||||
}
|
||||
|
||||
// Returns the Glslang message rules for the given target environment,
|
||||
// source language, and whether we want HLSL offset rules. We assume
|
||||
// only valid combinations are used.
|
||||
EShMessages GetMessageRules(shaderc_util::Compiler::TargetEnv env,
|
||||
shaderc_util::Compiler::SourceLanguage lang,
|
||||
bool hlsl_offsets, bool hlsl_16bit_types,
|
||||
bool debug_info) {
|
||||
using shaderc_util::Compiler;
|
||||
EShMessages result = EShMsgCascadingErrors;
|
||||
if (lang == Compiler::SourceLanguage::HLSL) {
|
||||
result = static_cast<EShMessages>(result | EShMsgReadHlsl);
|
||||
}
|
||||
switch (env) {
|
||||
case Compiler::TargetEnv::OpenGLCompat:
|
||||
// The compiler will have already errored out before now.
|
||||
// But we need to handle this enum.
|
||||
break;
|
||||
case Compiler::TargetEnv::OpenGL:
|
||||
result = static_cast<EShMessages>(result | EShMsgSpvRules);
|
||||
break;
|
||||
case Compiler::TargetEnv::Vulkan:
|
||||
result =
|
||||
static_cast<EShMessages>(result | EShMsgSpvRules | EShMsgVulkanRules);
|
||||
break;
|
||||
}
|
||||
if (hlsl_offsets) {
|
||||
result = static_cast<EShMessages>(result | EShMsgHlslOffsets);
|
||||
}
|
||||
if (hlsl_16bit_types) {
|
||||
result = static_cast<EShMessages>(result | EShMsgHlslEnable16BitTypes);
|
||||
}
|
||||
if (debug_info) {
|
||||
result = static_cast<EShMessages>(result | EShMsgDebugInfo);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace shaderc_util {
|
||||
|
||||
unsigned int GlslangInitializer::initialize_count_ = 0;
|
||||
std::mutex* GlslangInitializer::glslang_mutex_ = nullptr;
|
||||
|
||||
GlslangInitializer::GlslangInitializer() {
|
||||
static std::mutex first_call_mutex;
|
||||
|
||||
// If this is the first call, glslang_mutex_ needs to be created, but in
|
||||
// thread safe manner.
|
||||
{
|
||||
const std::lock_guard<std::mutex> first_call_lock(first_call_mutex);
|
||||
if (glslang_mutex_ == nullptr) {
|
||||
glslang_mutex_ = new std::mutex();
|
||||
}
|
||||
}
|
||||
|
||||
const std::lock_guard<std::mutex> glslang_lock(*glslang_mutex_);
|
||||
|
||||
if (initialize_count_ == 0) {
|
||||
glslang::InitializeProcess();
|
||||
}
|
||||
|
||||
initialize_count_++;
|
||||
}
|
||||
|
||||
GlslangInitializer::~GlslangInitializer() {
|
||||
const std::lock_guard<std::mutex> glslang_lock(*glslang_mutex_);
|
||||
|
||||
initialize_count_--;
|
||||
|
||||
if (initialize_count_ == 0) {
|
||||
glslang::FinalizeProcess();
|
||||
// There is no delete for glslang_mutex_ here, because we cannot guarantee
|
||||
// there isn't a caller waiting for glslang_mutex_ in GlslangInitializer().
|
||||
//
|
||||
// This means that this class does leak one std::mutex worth of memory after
|
||||
// the final instance is destroyed, but this allows us to defer allocating
|
||||
// and constructing until we are sure we need to.
|
||||
}
|
||||
}
|
||||
|
||||
void Compiler::SetLimit(Compiler::Limit limit, int value) {
|
||||
switch (limit) {
|
||||
#define RESOURCE(NAME, FIELD, CNAME) \
|
||||
case Limit::NAME: \
|
||||
limits_.FIELD = value; \
|
||||
break;
|
||||
#include "libshaderc_util/resources.inc"
|
||||
#undef RESOURCE
|
||||
}
|
||||
}
|
||||
|
||||
int Compiler::GetLimit(Compiler::Limit limit) const {
|
||||
switch (limit) {
|
||||
#define RESOURCE(NAME, FIELD, CNAME) \
|
||||
case Limit::NAME: \
|
||||
return limits_.FIELD;
|
||||
#include "libshaderc_util/resources.inc"
|
||||
#undef RESOURCE
|
||||
}
|
||||
return 0; // Unreachable
|
||||
}
|
||||
|
||||
std::tuple<bool, std::vector<uint32_t>, size_t> Compiler::Compile(
|
||||
const string_piece& input_source_string, EShLanguage forced_shader_stage,
|
||||
const std::string& error_tag, const char* entry_point_name,
|
||||
const std::function<EShLanguage(std::ostream* error_stream,
|
||||
const string_piece& error_tag)>&
|
||||
stage_callback,
|
||||
CountingIncluder& includer, OutputType output_type,
|
||||
std::ostream* error_stream, size_t* total_warnings, size_t* total_errors) const {
|
||||
// Compilation results to be returned:
|
||||
// Initialize the result tuple as a failed compilation. In error cases, we
|
||||
// should return result_tuple directly without setting its members.
|
||||
auto result_tuple =
|
||||
std::make_tuple(false, std::vector<uint32_t>(), (size_t)0u);
|
||||
// Get the reference of the members of the result tuple. We should set their
|
||||
// values for succeeded compilation before returning the result tuple.
|
||||
bool& succeeded = std::get<0>(result_tuple);
|
||||
std::vector<uint32_t>& compilation_output_data = std::get<1>(result_tuple);
|
||||
size_t& compilation_output_data_size_in_bytes = std::get<2>(result_tuple);
|
||||
|
||||
// Check target environment.
|
||||
const auto target_client_info = GetGlslangClientInfo(
|
||||
error_tag, target_env_, target_env_version_,
|
||||
target_spirv_version_, target_spirv_version_is_forced_);
|
||||
if (!target_client_info.error.empty()) {
|
||||
*error_stream << target_client_info.error;
|
||||
*total_warnings = 0;
|
||||
*total_errors = 1;
|
||||
return result_tuple;
|
||||
}
|
||||
|
||||
EShLanguage used_shader_stage = forced_shader_stage;
|
||||
const std::string macro_definitions =
|
||||
shaderc_util::format(predefined_macros_, "#define ", " ", "\n");
|
||||
const std::string pound_extension =
|
||||
"#extension GL_GOOGLE_include_directive : enable\n";
|
||||
const std::string preamble = macro_definitions + pound_extension;
|
||||
|
||||
std::string preprocessed_shader;
|
||||
|
||||
// If only preprocessing, we definitely need to preprocess. Otherwise, if
|
||||
// we don't know the stage until now, we need the preprocessed shader to
|
||||
// deduce the shader stage.
|
||||
if (output_type == OutputType::PreprocessedText ||
|
||||
used_shader_stage == EShLangCount) {
|
||||
bool success;
|
||||
std::string glslang_errors;
|
||||
std::tie(success, preprocessed_shader, glslang_errors) =
|
||||
PreprocessShader(error_tag, input_source_string, preamble, includer);
|
||||
|
||||
success &= PrintFilteredErrors(error_tag, error_stream, warnings_as_errors_,
|
||||
/* suppress_warnings = */ true,
|
||||
glslang_errors.c_str(), total_warnings,
|
||||
total_errors);
|
||||
if (!success) return result_tuple;
|
||||
// Because of the behavior change of the #line directive, the #line
|
||||
// directive introducing each file's content must use the syntax for the
|
||||
// specified version. So we need to probe this shader's version and
|
||||
// profile.
|
||||
int version;
|
||||
EProfile profile;
|
||||
std::tie(version, profile) = DeduceVersionProfile(preprocessed_shader);
|
||||
const bool is_for_next_line = LineDirectiveIsForNextLine(version, profile);
|
||||
|
||||
preprocessed_shader =
|
||||
CleanupPreamble(preprocessed_shader, error_tag, pound_extension,
|
||||
includer.num_include_directives(), is_for_next_line);
|
||||
|
||||
if (output_type == OutputType::PreprocessedText) {
|
||||
// Set the values of the result tuple.
|
||||
succeeded = true;
|
||||
compilation_output_data = ConvertStringToVector(preprocessed_shader);
|
||||
compilation_output_data_size_in_bytes = preprocessed_shader.size();
|
||||
return result_tuple;
|
||||
} else if (used_shader_stage == EShLangCount) {
|
||||
std::string errors;
|
||||
std::tie(used_shader_stage, errors) =
|
||||
GetShaderStageFromSourceCode(error_tag, preprocessed_shader);
|
||||
if (!errors.empty()) {
|
||||
*error_stream << errors;
|
||||
return result_tuple;
|
||||
}
|
||||
if (used_shader_stage == EShLangCount) {
|
||||
if ((used_shader_stage = stage_callback(error_stream, error_tag)) ==
|
||||
EShLangCount) {
|
||||
return result_tuple;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Parsing requires its own Glslang symbol tables.
|
||||
glslang::TShader shader(used_shader_stage);
|
||||
const char* shader_strings = input_source_string.data();
|
||||
const int shader_lengths = static_cast<int>(input_source_string.size());
|
||||
const char* string_names = error_tag.c_str();
|
||||
shader.setStringsWithLengthsAndNames(&shader_strings, &shader_lengths,
|
||||
&string_names, 1);
|
||||
shader.setPreamble(preamble.c_str());
|
||||
shader.setEntryPoint(entry_point_name);
|
||||
shader.setAutoMapBindings(auto_bind_uniforms_);
|
||||
if (auto_combined_image_sampler_) {
|
||||
shader.setTextureSamplerTransformMode(EShTexSampTransUpgradeTextureRemoveSampler);
|
||||
}
|
||||
shader.setAutoMapLocations(auto_map_locations_);
|
||||
const auto& bases = auto_binding_base_[static_cast<int>(used_shader_stage)];
|
||||
shader.setShiftImageBinding(bases[static_cast<int>(UniformKind::Image)]);
|
||||
shader.setShiftSamplerBinding(bases[static_cast<int>(UniformKind::Sampler)]);
|
||||
shader.setShiftTextureBinding(bases[static_cast<int>(UniformKind::Texture)]);
|
||||
shader.setShiftUboBinding(bases[static_cast<int>(UniformKind::Buffer)]);
|
||||
shader.setShiftSsboBinding(
|
||||
bases[static_cast<int>(UniformKind::StorageBuffer)]);
|
||||
shader.setShiftUavBinding(
|
||||
bases[static_cast<int>(UniformKind::UnorderedAccessView)]);
|
||||
shader.setHlslIoMapping(hlsl_iomap_);
|
||||
shader.setResourceSetBinding(
|
||||
hlsl_explicit_bindings_[static_cast<int>(used_shader_stage)]);
|
||||
shader.setEnvClient(target_client_info.client,
|
||||
target_client_info.client_version);
|
||||
shader.setEnvTarget(target_client_info.target_language,
|
||||
target_client_info.target_language_version);
|
||||
if (hlsl_functionality1_enabled_) {
|
||||
shader.setEnvTargetHlslFunctionality1();
|
||||
}
|
||||
if (vulkan_rules_relaxed_) {
|
||||
glslang::EShSource language = glslang::EShSourceNone;
|
||||
switch(source_language_) {
|
||||
case SourceLanguage::GLSL:
|
||||
language = glslang::EShSourceGlsl;
|
||||
break;
|
||||
case SourceLanguage::HLSL:
|
||||
language = glslang::EShSourceHlsl;
|
||||
break;
|
||||
}
|
||||
// This option will only be used if the Vulkan client is used.
|
||||
// If new versions of GL_KHR_vulkan_glsl come out, it would make sense to
|
||||
// let callers specify which version to use. For now, just use 100.
|
||||
shader.setEnvInput(language, used_shader_stage, glslang::EShClientVulkan, 100);
|
||||
shader.setEnvInputVulkanRulesRelaxed();
|
||||
}
|
||||
shader.setInvertY(invert_y_enabled_);
|
||||
shader.setNanMinMaxClamp(nan_clamp_);
|
||||
|
||||
const EShMessages rules =
|
||||
GetMessageRules(target_env_, source_language_, hlsl_offsets_,
|
||||
hlsl_16bit_types_enabled_, generate_debug_info_);
|
||||
|
||||
bool success = shader.parse(&limits_, default_version_, default_profile_,
|
||||
force_version_profile_, kNotForwardCompatible,
|
||||
rules, includer);
|
||||
|
||||
success &= PrintFilteredErrors(error_tag, error_stream, warnings_as_errors_,
|
||||
suppress_warnings_, shader.getInfoLog(),
|
||||
total_warnings, total_errors);
|
||||
if (!success) return result_tuple;
|
||||
|
||||
glslang::TProgram program;
|
||||
program.addShader(&shader);
|
||||
success = program.link(EShMsgDefault) && program.mapIO();
|
||||
success &= PrintFilteredErrors(error_tag, error_stream, warnings_as_errors_,
|
||||
suppress_warnings_, program.getInfoLog(),
|
||||
total_warnings, total_errors);
|
||||
if (!success) return result_tuple;
|
||||
|
||||
// 'spirv' is an alias for the compilation_output_data. This alias is added
|
||||
// to serve as an input for the call to DissassemblyBinary.
|
||||
std::vector<uint32_t>& spirv = compilation_output_data;
|
||||
glslang::SpvOptions options;
|
||||
options.generateDebugInfo = generate_debug_info_;
|
||||
options.disableOptimizer = true;
|
||||
options.optimizeSize = false;
|
||||
options.emitNonSemanticShaderDebugInfo =
|
||||
generate_debug_info_ && emit_non_semantic_debug_info_;
|
||||
options.emitNonSemanticShaderDebugSource =
|
||||
generate_debug_info_ && emit_non_semantic_debug_info_;
|
||||
|
||||
// Note the call to GlslangToSpv also populates compilation_output_data.
|
||||
glslang::GlslangToSpv(*program.getIntermediate(used_shader_stage), spirv,
|
||||
&options);
|
||||
|
||||
// Set the tool field (the top 16-bits) in the generator word to
|
||||
// 'Shaderc over Glslang'.
|
||||
const uint32_t shaderc_generator_word = 13; // From SPIR-V XML Registry
|
||||
const uint32_t generator_word_index = 2; // SPIR-V 2.3: Physical layout
|
||||
assert(spirv.size() > generator_word_index);
|
||||
spirv[generator_word_index] =
|
||||
(spirv[generator_word_index] & 0xffff) | (shaderc_generator_word << 16);
|
||||
|
||||
std::vector<PassId> opt_passes;
|
||||
|
||||
if (hlsl_legalization_enabled_ && source_language_ == SourceLanguage::HLSL) {
|
||||
// If from HLSL, run this passes to "legalize" the SPIR-V for Vulkan
|
||||
// eg. forward and remove memory writes of opaque types.
|
||||
opt_passes.push_back(PassId::kLegalizationPasses);
|
||||
}
|
||||
|
||||
opt_passes.insert(opt_passes.end(), enabled_opt_passes_.begin(),
|
||||
enabled_opt_passes_.end());
|
||||
|
||||
if (!opt_passes.empty()) {
|
||||
spvtools::OptimizerOptions opt_options;
|
||||
opt_options.set_preserve_bindings(preserve_bindings_);
|
||||
|
||||
std::string opt_errors;
|
||||
if (!SpirvToolsOptimize(target_env_, target_env_version_, opt_passes,
|
||||
opt_options, &spirv, &opt_errors)) {
|
||||
*error_stream << "shaderc: internal error: compilation succeeded but "
|
||||
"failed to optimize: "
|
||||
<< opt_errors << "\n";
|
||||
return result_tuple;
|
||||
}
|
||||
}
|
||||
|
||||
if (output_type == OutputType::SpirvAssemblyText) {
|
||||
std::string text_or_error;
|
||||
if (!SpirvToolsDisassemble(target_env_, target_env_version_, spirv,
|
||||
&text_or_error)) {
|
||||
*error_stream << "shaderc: internal error: compilation succeeded but "
|
||||
"failed to disassemble: "
|
||||
<< text_or_error << "\n";
|
||||
return result_tuple;
|
||||
}
|
||||
succeeded = true;
|
||||
compilation_output_data = ConvertStringToVector(text_or_error);
|
||||
compilation_output_data_size_in_bytes = text_or_error.size();
|
||||
return result_tuple;
|
||||
} else {
|
||||
succeeded = true;
|
||||
// Note compilation_output_data is already populated in GlslangToSpv().
|
||||
compilation_output_data_size_in_bytes = spirv.size() * sizeof(spirv[0]);
|
||||
return result_tuple;
|
||||
}
|
||||
}
|
||||
|
||||
void Compiler::AddMacroDefinition(const char* macro, size_t macro_length,
|
||||
const char* definition,
|
||||
size_t definition_length) {
|
||||
predefined_macros_[std::string(macro, macro_length)] =
|
||||
definition ? std::string(definition, definition_length) : "";
|
||||
}
|
||||
|
||||
void Compiler::SetTargetEnv(Compiler::TargetEnv env,
|
||||
Compiler::TargetEnvVersion version) {
|
||||
target_env_ = env;
|
||||
target_env_version_ = version;
|
||||
}
|
||||
|
||||
void Compiler::SetTargetSpirv(Compiler::SpirvVersion version) {
|
||||
target_spirv_version_ = version;
|
||||
target_spirv_version_is_forced_ = true;
|
||||
}
|
||||
|
||||
void Compiler::SetSourceLanguage(Compiler::SourceLanguage lang) {
|
||||
source_language_ = lang;
|
||||
}
|
||||
|
||||
void Compiler::SetForcedVersionProfile(int version, EProfile profile) {
|
||||
default_version_ = version;
|
||||
default_profile_ = profile;
|
||||
force_version_profile_ = true;
|
||||
}
|
||||
|
||||
void Compiler::SetWarningsAsErrors() { warnings_as_errors_ = true; }
|
||||
|
||||
void Compiler::SetGenerateDebugInfo() {
|
||||
generate_debug_info_ = true;
|
||||
for (size_t i = 0; i < enabled_opt_passes_.size(); ++i) {
|
||||
if (enabled_opt_passes_[i] == PassId::kStripDebugInfo) {
|
||||
enabled_opt_passes_[i] = PassId::kNullPass;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Compiler::SetEmitNonSemanticDebugInfo() {
|
||||
emit_non_semantic_debug_info_ = true;
|
||||
}
|
||||
|
||||
void Compiler::SetOptimizationLevel(Compiler::OptimizationLevel level) {
|
||||
// Clear previous settings first.
|
||||
enabled_opt_passes_.clear();
|
||||
|
||||
switch (level) {
|
||||
case OptimizationLevel::Size:
|
||||
if (!generate_debug_info_) {
|
||||
enabled_opt_passes_.push_back(PassId::kStripDebugInfo);
|
||||
}
|
||||
enabled_opt_passes_.push_back(PassId::kSizePasses);
|
||||
break;
|
||||
case OptimizationLevel::Performance:
|
||||
if (!generate_debug_info_) {
|
||||
enabled_opt_passes_.push_back(PassId::kStripDebugInfo);
|
||||
}
|
||||
enabled_opt_passes_.push_back(PassId::kPerformancePasses);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Compiler::EnableHlslLegalization(bool hlsl_legalization_enabled) {
|
||||
hlsl_legalization_enabled_ = hlsl_legalization_enabled;
|
||||
}
|
||||
|
||||
void Compiler::EnableHlslFunctionality1(bool enable) {
|
||||
hlsl_functionality1_enabled_ = enable;
|
||||
}
|
||||
|
||||
void Compiler::SetVulkanRulesRelaxed(bool enable) {
|
||||
vulkan_rules_relaxed_ = enable;
|
||||
}
|
||||
|
||||
void Compiler::EnableHlsl16BitTypes(bool enable) {
|
||||
hlsl_16bit_types_enabled_ = enable;
|
||||
}
|
||||
|
||||
void Compiler::EnableInvertY(bool enable) { invert_y_enabled_ = enable; }
|
||||
|
||||
void Compiler::SetNanClamp(bool enable) { nan_clamp_ = enable; }
|
||||
|
||||
void Compiler::SetSuppressWarnings() { suppress_warnings_ = true; }
|
||||
|
||||
std::tuple<bool, std::string, std::string> Compiler::PreprocessShader(
|
||||
const std::string& error_tag, const string_piece& shader_source,
|
||||
const string_piece& shader_preamble, CountingIncluder& includer) const {
|
||||
// The stage does not matter for preprocessing.
|
||||
glslang::TShader shader(EShLangVertex);
|
||||
const char* shader_strings = shader_source.data();
|
||||
const int shader_lengths = static_cast<int>(shader_source.size());
|
||||
const char* string_names = error_tag.c_str();
|
||||
shader.setStringsWithLengthsAndNames(&shader_strings, &shader_lengths,
|
||||
&string_names, 1);
|
||||
shader.setPreamble(shader_preamble.data());
|
||||
auto target_client_info = GetGlslangClientInfo(
|
||||
error_tag, target_env_, target_env_version_,
|
||||
target_spirv_version_, target_spirv_version_is_forced_);
|
||||
if (!target_client_info.error.empty()) {
|
||||
return std::make_tuple(false, "", target_client_info.error);
|
||||
}
|
||||
shader.setEnvClient(target_client_info.client,
|
||||
target_client_info.client_version);
|
||||
if (hlsl_functionality1_enabled_) {
|
||||
shader.setEnvTargetHlslFunctionality1();
|
||||
}
|
||||
shader.setInvertY(invert_y_enabled_);
|
||||
shader.setNanMinMaxClamp(nan_clamp_);
|
||||
|
||||
// The preprocessor might be sensitive to the target environment.
|
||||
// So combine the existing rules with the just-give-me-preprocessor-output
|
||||
// flag.
|
||||
const auto rules = static_cast<EShMessages>(
|
||||
EShMsgOnlyPreprocessor |
|
||||
GetMessageRules(target_env_, source_language_, hlsl_offsets_,
|
||||
hlsl_16bit_types_enabled_, false));
|
||||
|
||||
std::string preprocessed_shader;
|
||||
const bool success = shader.preprocess(
|
||||
&limits_, default_version_, default_profile_, force_version_profile_,
|
||||
kNotForwardCompatible, rules, &preprocessed_shader, includer);
|
||||
|
||||
if (success) {
|
||||
return std::make_tuple(true, preprocessed_shader, shader.getInfoLog());
|
||||
}
|
||||
return std::make_tuple(false, "", shader.getInfoLog());
|
||||
}
|
||||
|
||||
std::string Compiler::CleanupPreamble(const string_piece& preprocessed_shader,
|
||||
const string_piece& error_tag,
|
||||
const string_piece& pound_extension,
|
||||
int num_include_directives,
|
||||
bool is_for_next_line) const {
|
||||
// Those #define directives in preamble will become empty lines after
|
||||
// preprocessing. We also injected an #extension directive to turn on #include
|
||||
// directive support. In the original preprocessing output from glslang, it
|
||||
// appears before the user source string. We need to do proper adjustment:
|
||||
// * Remove empty lines generated from #define directives in preamble.
|
||||
// * If there is no #include directive in the source code, we do not need to
|
||||
// output the injected #extension directive. Otherwise,
|
||||
// * If there exists a #version directive in the source code, it should be
|
||||
// placed at the first line. Its original line will be filled with an empty
|
||||
// line as placeholder to maintain the code structure.
|
||||
|
||||
const std::vector<string_piece> lines =
|
||||
preprocessed_shader.get_fields('\n', /* keep_delimiter = */ true);
|
||||
|
||||
std::ostringstream output_stream;
|
||||
|
||||
size_t pound_extension_index = lines.size();
|
||||
size_t pound_version_index = lines.size();
|
||||
for (size_t i = 0; i < lines.size(); ++i) {
|
||||
if (lines[i] == pound_extension) {
|
||||
pound_extension_index = std::min(i, pound_extension_index);
|
||||
} else if (lines[i].starts_with("#version")) {
|
||||
// In a preprocessed shader, directives are in a canonical format, so we
|
||||
// can confidently compare to '#version' verbatim, without worrying about
|
||||
// whitespace.
|
||||
pound_version_index = i;
|
||||
if (num_include_directives > 0) output_stream << lines[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
// We know that #extension directive exists and appears before #version
|
||||
// directive (if any).
|
||||
assert(pound_extension_index < lines.size());
|
||||
|
||||
for (size_t i = 0; i < pound_extension_index; ++i) {
|
||||
// All empty lines before the #line directive we injected are generated by
|
||||
// preprocessing preamble. Do not output them.
|
||||
if (lines[i].strip_whitespace().empty()) continue;
|
||||
output_stream << lines[i];
|
||||
}
|
||||
|
||||
if (num_include_directives > 0) {
|
||||
output_stream << pound_extension;
|
||||
// Also output a #line directive for the main file.
|
||||
output_stream << GetLineDirective(is_for_next_line, error_tag);
|
||||
}
|
||||
|
||||
for (size_t i = pound_extension_index + 1; i < lines.size(); ++i) {
|
||||
if (i == pound_version_index) {
|
||||
if (num_include_directives > 0) {
|
||||
output_stream << "\n";
|
||||
} else {
|
||||
output_stream << lines[i];
|
||||
}
|
||||
} else {
|
||||
output_stream << lines[i];
|
||||
}
|
||||
}
|
||||
|
||||
return output_stream.str();
|
||||
}
|
||||
|
||||
std::pair<EShLanguage, std::string> Compiler::GetShaderStageFromSourceCode(
|
||||
string_piece filename, const std::string& preprocessed_shader) const {
|
||||
const string_piece kPragmaShaderStageDirective = "#pragma shader_stage";
|
||||
const string_piece kLineDirective = "#line";
|
||||
|
||||
int version;
|
||||
EProfile profile;
|
||||
std::tie(version, profile) = DeduceVersionProfile(preprocessed_shader);
|
||||
const bool is_for_next_line = LineDirectiveIsForNextLine(version, profile);
|
||||
|
||||
std::vector<string_piece> lines =
|
||||
string_piece(preprocessed_shader).get_fields('\n');
|
||||
// The filename, logical line number (which starts from 1 and is sensitive to
|
||||
// #line directives), and stage value for #pragma shader_stage() directives.
|
||||
std::vector<std::tuple<string_piece, size_t, string_piece>> stages;
|
||||
// The physical line numbers of the first #pragma shader_stage() line and
|
||||
// first non-preprocessing line in the preprocessed shader text.
|
||||
size_t first_pragma_physical_line = lines.size() + 1;
|
||||
size_t first_non_pp_line = lines.size() + 1;
|
||||
|
||||
for (size_t i = 0, logical_line_no = 1; i < lines.size(); ++i) {
|
||||
const string_piece current_line = lines[i].strip_whitespace();
|
||||
if (current_line.starts_with(kPragmaShaderStageDirective)) {
|
||||
const string_piece stage_value =
|
||||
current_line.substr(kPragmaShaderStageDirective.size()).strip("()");
|
||||
stages.emplace_back(filename, logical_line_no, stage_value);
|
||||
first_pragma_physical_line = std::min(first_pragma_physical_line, i + 1);
|
||||
} else if (!current_line.empty() && !current_line.starts_with("#")) {
|
||||
first_non_pp_line = std::min(first_non_pp_line, i + 1);
|
||||
}
|
||||
|
||||
// Update logical line number for the next line.
|
||||
if (current_line.starts_with(kLineDirective)) {
|
||||
string_piece name;
|
||||
std::tie(logical_line_no, name) = DecodeLineDirective(current_line);
|
||||
if (!name.empty()) filename = name;
|
||||
// Note that for core profile, the meaning of #line changed since version
|
||||
// 330. The line number given by #line used to mean the logical line
|
||||
// number of the #line line. Now it means the logical line number of the
|
||||
// next line after the #line line.
|
||||
if (!is_for_next_line) ++logical_line_no;
|
||||
} else {
|
||||
++logical_line_no;
|
||||
}
|
||||
}
|
||||
if (stages.empty()) return std::make_pair(EShLangCount, "");
|
||||
|
||||
std::string error_message;
|
||||
|
||||
const string_piece& first_pragma_filename = std::get<0>(stages[0]);
|
||||
const std::string first_pragma_line = std::to_string(std::get<1>(stages[0]));
|
||||
const string_piece& first_pragma_stage = std::get<2>(stages[0]);
|
||||
|
||||
if (first_pragma_physical_line > first_non_pp_line) {
|
||||
error_message += first_pragma_filename.str() + ":" + first_pragma_line +
|
||||
": error: '#pragma': the first 'shader_stage' #pragma "
|
||||
"must appear before any non-preprocessing code\n";
|
||||
}
|
||||
|
||||
EShLanguage stage = MapStageNameToLanguage(first_pragma_stage);
|
||||
if (stage == EShLangCount) {
|
||||
error_message +=
|
||||
first_pragma_filename.str() + ":" + first_pragma_line +
|
||||
": error: '#pragma': invalid stage for 'shader_stage' #pragma: '" +
|
||||
first_pragma_stage.str() + "'\n";
|
||||
}
|
||||
|
||||
for (size_t i = 1; i < stages.size(); ++i) {
|
||||
const string_piece& current_stage = std::get<2>(stages[i]);
|
||||
if (current_stage != first_pragma_stage) {
|
||||
const string_piece& current_filename = std::get<0>(stages[i]);
|
||||
const std::string current_line = std::to_string(std::get<1>(stages[i]));
|
||||
error_message += current_filename.str() + ":" + current_line +
|
||||
": error: '#pragma': conflicting stages for "
|
||||
"'shader_stage' #pragma: '" +
|
||||
current_stage.str() + "' (was '" +
|
||||
first_pragma_stage.str() + "' at " +
|
||||
first_pragma_filename.str() + ":" + first_pragma_line +
|
||||
")\n";
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_pair(error_message.empty() ? stage : EShLangCount,
|
||||
error_message);
|
||||
}
|
||||
|
||||
std::pair<int, EProfile> Compiler::DeduceVersionProfile(
|
||||
const std::string& preprocessed_shader) const {
|
||||
int version = default_version_;
|
||||
EProfile profile = default_profile_;
|
||||
if (!force_version_profile_) {
|
||||
std::tie(version, profile) =
|
||||
GetVersionProfileFromSourceCode(preprocessed_shader);
|
||||
if (version == 0 && profile == ENoProfile) {
|
||||
version = default_version_;
|
||||
profile = default_profile_;
|
||||
}
|
||||
}
|
||||
return std::make_pair(version, profile);
|
||||
}
|
||||
|
||||
std::pair<int, EProfile> Compiler::GetVersionProfileFromSourceCode(
|
||||
const std::string& preprocessed_shader) const {
|
||||
string_piece pound_version = preprocessed_shader;
|
||||
const size_t pound_version_loc = pound_version.find("#version");
|
||||
if (pound_version_loc == string_piece::npos) {
|
||||
return std::make_pair(0, ENoProfile);
|
||||
}
|
||||
pound_version =
|
||||
pound_version.substr(pound_version_loc + std::strlen("#version"));
|
||||
pound_version = pound_version.substr(0, pound_version.find_first_of("\n"));
|
||||
|
||||
std::string version_profile;
|
||||
for (const auto character : pound_version) {
|
||||
if (character != ' ') version_profile += character;
|
||||
}
|
||||
|
||||
int version;
|
||||
EProfile profile;
|
||||
if (!ParseVersionProfile(version_profile, &version, &profile)) {
|
||||
return std::make_pair(0, ENoProfile);
|
||||
}
|
||||
return std::make_pair(version, profile);
|
||||
}
|
||||
|
||||
// Converts a string to a vector of uint32_t by copying the content of a given
|
||||
// string to a vector<uint32_t> and returns it. Appends '\0' at the end if extra
|
||||
// bytes are required to complete the last element.
|
||||
std::vector<uint32_t> ConvertStringToVector(const std::string& str) {
|
||||
size_t num_bytes_str = str.size() + 1u;
|
||||
size_t vector_length =
|
||||
(num_bytes_str + sizeof(uint32_t) - 1) / sizeof(uint32_t);
|
||||
std::vector<uint32_t> result_vec(vector_length, 0);
|
||||
std::strncpy(reinterpret_cast<char*>(result_vec.data()), str.c_str(),
|
||||
str.size());
|
||||
return result_vec;
|
||||
}
|
||||
|
||||
GlslangClientInfo GetGlslangClientInfo(
|
||||
const std::string& error_tag, shaderc_util::Compiler::TargetEnv env,
|
||||
shaderc_util::Compiler::TargetEnvVersion env_version,
|
||||
shaderc_util::Compiler::SpirvVersion spv_version,
|
||||
bool spv_version_is_forced) {
|
||||
GlslangClientInfo result;
|
||||
std::ostringstream errs;
|
||||
|
||||
using shaderc_util::Compiler;
|
||||
switch (env) {
|
||||
case Compiler::TargetEnv::Vulkan:
|
||||
result.client = glslang::EShClientVulkan;
|
||||
if (env_version == Compiler::TargetEnvVersion::Default ||
|
||||
env_version == Compiler::TargetEnvVersion::Vulkan_1_0) {
|
||||
result.client_version = glslang::EShTargetVulkan_1_0;
|
||||
} else if (env_version == Compiler::TargetEnvVersion::Vulkan_1_1) {
|
||||
result.client_version = glslang::EShTargetVulkan_1_1;
|
||||
result.target_language_version = glslang::EShTargetSpv_1_3;
|
||||
} else if (env_version == Compiler::TargetEnvVersion::Vulkan_1_2) {
|
||||
result.client_version = glslang::EShTargetVulkan_1_2;
|
||||
result.target_language_version = glslang::EShTargetSpv_1_5;
|
||||
} else if (env_version == Compiler::TargetEnvVersion::Vulkan_1_3) {
|
||||
result.client_version = glslang::EShTargetVulkan_1_3;
|
||||
result.target_language_version = glslang::EShTargetSpv_1_6;
|
||||
} else {
|
||||
errs << "error:" << error_tag << ": Invalid target client version "
|
||||
<< static_cast<uint32_t>(env_version) << " for Vulkan environment "
|
||||
<< int(env);
|
||||
}
|
||||
break;
|
||||
case Compiler::TargetEnv::OpenGLCompat:
|
||||
errs << "error: OpenGL compatibility profile is not supported";
|
||||
break;
|
||||
case Compiler::TargetEnv::OpenGL:
|
||||
result.client = glslang::EShClientOpenGL;
|
||||
if (env_version == Compiler::TargetEnvVersion::Default ||
|
||||
env_version == Compiler::TargetEnvVersion::OpenGL_4_5) {
|
||||
result.client_version = glslang::EShTargetOpenGL_450;
|
||||
} else {
|
||||
errs << "error:" << error_tag << ": Invalid target client version "
|
||||
<< static_cast<uint32_t>(env_version) << " for OpenGL environment "
|
||||
<< int(env);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
errs << "error:" << error_tag << ": Invalid target client environment "
|
||||
<< int(env);
|
||||
break;
|
||||
}
|
||||
|
||||
if (spv_version_is_forced && errs.str().empty()) {
|
||||
switch (spv_version) {
|
||||
case Compiler::SpirvVersion::v1_0:
|
||||
result.target_language_version = glslang::EShTargetSpv_1_0;
|
||||
break;
|
||||
case Compiler::SpirvVersion::v1_1:
|
||||
result.target_language_version = glslang::EShTargetSpv_1_1;
|
||||
break;
|
||||
case Compiler::SpirvVersion::v1_2:
|
||||
result.target_language_version = glslang::EShTargetSpv_1_2;
|
||||
break;
|
||||
case Compiler::SpirvVersion::v1_3:
|
||||
result.target_language_version = glslang::EShTargetSpv_1_3;
|
||||
break;
|
||||
case Compiler::SpirvVersion::v1_4:
|
||||
result.target_language_version = glslang::EShTargetSpv_1_4;
|
||||
break;
|
||||
case Compiler::SpirvVersion::v1_5:
|
||||
result.target_language_version = glslang::EShTargetSpv_1_5;
|
||||
break;
|
||||
case Compiler::SpirvVersion::v1_6:
|
||||
result.target_language_version = glslang::EShTargetSpv_1_6;
|
||||
break;
|
||||
default:
|
||||
errs << "error:" << error_tag << ": Unknown SPIR-V version " << std::hex
|
||||
<< uint32_t(spv_version);
|
||||
break;
|
||||
}
|
||||
}
|
||||
result.error = errs.str();
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace shaderc_util
|
||||
974
3rdparty/shaderc/libshaderc_util/src/compiler_test.cc
vendored
Normal file
974
3rdparty/shaderc/libshaderc_util/src/compiler_test.cc
vendored
Normal file
@@ -0,0 +1,974 @@
|
||||
// Copyright 2015 The Shaderc Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "libshaderc_util/compiler.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
#include "death_test.h"
|
||||
#include "libshaderc_util/counting_includer.h"
|
||||
#include "libshaderc_util/spirv_tools_wrapper.h"
|
||||
|
||||
namespace {
|
||||
|
||||
using shaderc_util::Compiler;
|
||||
using shaderc_util::GlslangClientInfo;
|
||||
using ::testing::Eq;
|
||||
using ::testing::HasSubstr;
|
||||
using ::testing::Not;
|
||||
|
||||
// A trivial vertex shader
|
||||
const char kVertexShader[] =
|
||||
"#version 140\n"
|
||||
"void main() {}";
|
||||
|
||||
// A shader that parses under OpenGL compatibility profile rules.
|
||||
// It does not compile because Glslang does not support SPIR-V
|
||||
// code generation for OpenGL compatibility profile.
|
||||
const char kOpenGLCompatibilityFragShader[] =
|
||||
R"(#version 140
|
||||
uniform highp sampler2D tex;
|
||||
void main() {
|
||||
gl_FragColor = texture2D(tex, vec2(0.0,0.0));
|
||||
})";
|
||||
|
||||
// A shader that compiles under OpenGL core profile rules.
|
||||
const char kOpenGLVertexShader[] =
|
||||
R"(#version 330
|
||||
void main() { int t = gl_VertexID; })";
|
||||
|
||||
// A shader that compiles under OpenGL core profile rules, even when
|
||||
// deducing the stage.
|
||||
const char kOpenGLVertexShaderDeducibleStage[] =
|
||||
R"(#version 330
|
||||
#pragma shader_stage(vertex)
|
||||
void main() { int t = gl_VertexID; })";
|
||||
|
||||
// A shader that compiles under Vulkan rules.
|
||||
// See the GL_KHR_vuklan_glsl extension to GLSL.
|
||||
const char kVulkanVertexShader[] =
|
||||
R"(#version 310 es
|
||||
void main() { int t = gl_VertexIndex; })";
|
||||
|
||||
// A shader that needs valueless macro predefinition E, to be compiled
|
||||
// successfully.
|
||||
const std::string kValuelessPredefinitionShader =
|
||||
"#version 140\n"
|
||||
"#ifdef E\n"
|
||||
"void main(){}\n"
|
||||
"#else\n"
|
||||
"#error\n"
|
||||
"#endif";
|
||||
|
||||
// An HLSL vertex shader.
|
||||
const char kHlslVertexShader[] =
|
||||
R"(float4 EntryPoint(uint index : SV_VERTEXID) : SV_POSITION
|
||||
{ return float4(1.0, 2.0, 3.0, 4.0); })";
|
||||
|
||||
// A GLSL fragment shader without bindings for its uniforms.
|
||||
// This also can be compiled as a vertex or compute shader.
|
||||
const char kGlslFragShaderNoExplicitBinding[] =
|
||||
R"(#version 450
|
||||
#extension GL_ARB_sparse_texture2: enable
|
||||
uniform texture2D my_tex;
|
||||
uniform sampler my_sam;
|
||||
layout(rgba32f) uniform image2D my_img;
|
||||
layout(rgba32f) uniform imageBuffer my_imbuf;
|
||||
uniform block { float x; float y; } my_ubo;
|
||||
void main() {
|
||||
texture(sampler2D(my_tex,my_sam),vec2(1.0));
|
||||
vec4 t = vec4(1.0);
|
||||
sparseImageLoadARB(my_img,ivec2(0),t);
|
||||
imageLoad(my_imbuf,2);
|
||||
float x = my_ubo.x;
|
||||
})";
|
||||
|
||||
// A GLSL vertex shader with the location defined for its non-opaque uniform
|
||||
// variable.
|
||||
const char kGlslVertShaderExplicitLocation[] =
|
||||
R"(#version 450
|
||||
layout(location = 10) uniform mat4 my_mat;
|
||||
layout(location = 0) in vec4 my_vec;
|
||||
void main(void) {
|
||||
gl_Position = my_mat * my_vec;
|
||||
})";
|
||||
|
||||
// A GLSL fragment shader with the location defined for its non-opaque uniform
|
||||
// variable.
|
||||
const char kGlslFragShaderOpaqueUniforms[] =
|
||||
R"(#version 320 es
|
||||
precision lowp float;
|
||||
|
||||
layout(location = 0) out vec4 oColor;
|
||||
layout(location = 0) uniform float a;
|
||||
void main(void) {
|
||||
oColor = vec4(1.0, 0.0, 0.0, a);
|
||||
})";
|
||||
|
||||
// A GLSL vertex shader without the location defined for its non-opaque uniform
|
||||
// variable.
|
||||
const char kGlslVertShaderNoExplicitLocation[] =
|
||||
R"(#version 450
|
||||
uniform mat4 my_mat;
|
||||
layout(location = 0) in vec4 my_vec;
|
||||
void main(void) {
|
||||
gl_Position = my_mat * my_vec;
|
||||
})";
|
||||
|
||||
// A GLSL vertex shader with a weirdly packed block.
|
||||
const char kGlslShaderWeirdPacking[] =
|
||||
R"(#version 450
|
||||
layout(set = 0, binding = 0)
|
||||
buffer B { float x; vec3 foo; } my_ssbo;
|
||||
void main() { my_ssbo.x = 1.0; })";
|
||||
|
||||
const char kHlslShaderForLegalizationTest[] = R"(
|
||||
struct CombinedTextureSampler {
|
||||
Texture2D tex;
|
||||
SamplerState sampl;
|
||||
};
|
||||
|
||||
float4 sampleTexture(CombinedTextureSampler c, float2 loc) {
|
||||
return c.tex.Sample(c.sampl, loc);
|
||||
};
|
||||
|
||||
[[vk::binding(0,0)]]
|
||||
Texture2D gTex;
|
||||
[[vk::binding(0,1)]]
|
||||
SamplerState gSampler;
|
||||
|
||||
float4 main(float2 loc: A) : SV_Target {
|
||||
CombinedTextureSampler cts;
|
||||
cts.tex = gTex;
|
||||
cts.sampl = gSampler;
|
||||
|
||||
return sampleTexture(cts, loc);
|
||||
})";
|
||||
|
||||
const char kHlslShaderWithCounterBuffer[] = R"(
|
||||
[[vk::binding(0,0)]]
|
||||
RWStructuredBuffer<float4> Ainc;
|
||||
float4 main() : SV_Target0 {
|
||||
return float4(Ainc.IncrementCounter(), 0, 0, 0);
|
||||
}
|
||||
)";
|
||||
|
||||
const char kGlslShaderWithClamp[] = R"(#version 450
|
||||
layout(location=0) in vec4 i;
|
||||
layout(location=0) out vec4 o;
|
||||
void main() { o = clamp(i, vec4(0.5), vec4(1.0)); }
|
||||
)";
|
||||
|
||||
// Returns the disassembly of the given SPIR-V binary, as a string.
|
||||
// Assumes the disassembly will be successful when targeting Vulkan.
|
||||
std::string Disassemble(const std::vector<uint32_t> binary) {
|
||||
std::string result;
|
||||
shaderc_util::SpirvToolsDisassemble(Compiler::TargetEnv::Vulkan,
|
||||
Compiler::TargetEnvVersion::Vulkan_1_3,
|
||||
binary, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// A CountingIncluder that never returns valid content for a requested
|
||||
// file inclusion.
|
||||
class DummyCountingIncluder : public shaderc_util::CountingIncluder {
|
||||
private:
|
||||
// Returns a pair of empty strings.
|
||||
virtual glslang::TShader::Includer::IncludeResult* include_delegate(
|
||||
const char*, const char*, IncludeType, size_t) override {
|
||||
return nullptr;
|
||||
}
|
||||
virtual void release_delegate(
|
||||
glslang::TShader::Includer::IncludeResult*) override {}
|
||||
};
|
||||
|
||||
// A test fixture for compiling GLSL shaders.
|
||||
class CompilerTest : public testing::Test {
|
||||
public:
|
||||
// Returns true if the given compiler successfully compiles the given shader
|
||||
// source for the given shader stage to the specified output type. No
|
||||
// includes are permitted, and shader stage deduction falls back to an invalid
|
||||
// shader stage.
|
||||
bool SimpleCompilationSucceedsForOutputType(
|
||||
std::string source, EShLanguage stage, Compiler::OutputType output_type) {
|
||||
shaderc_util::GlslangInitializer initializer;
|
||||
std::stringstream errors;
|
||||
size_t total_warnings = 0;
|
||||
size_t total_errors = 0;
|
||||
bool result = false;
|
||||
DummyCountingIncluder dummy_includer;
|
||||
std::tie(result, std::ignore, std::ignore) = compiler_.Compile(
|
||||
source, stage, "shader", "main", dummy_stage_callback_, dummy_includer,
|
||||
Compiler::OutputType::SpirvBinary, &errors, &total_warnings,
|
||||
&total_errors);
|
||||
errors_ = errors.str();
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns the result of SimpleCompilationSucceedsForOutputType, where
|
||||
// the output type is a SPIR-V binary module.
|
||||
bool SimpleCompilationSucceeds(std::string source, EShLanguage stage) {
|
||||
return SimpleCompilationSucceedsForOutputType(
|
||||
source, stage, Compiler::OutputType::SpirvBinary);
|
||||
}
|
||||
|
||||
// Returns the SPIR-V binary for a successful compilation of a shader.
|
||||
std::vector<uint32_t> SimpleCompilationBinary(std::string source,
|
||||
EShLanguage stage) {
|
||||
shaderc_util::GlslangInitializer initializer;
|
||||
std::stringstream errors;
|
||||
size_t total_warnings = 0;
|
||||
size_t total_errors = 0;
|
||||
bool result = false;
|
||||
DummyCountingIncluder dummy_includer;
|
||||
std::vector<uint32_t> words;
|
||||
std::tie(result, words, std::ignore) = compiler_.Compile(
|
||||
source, stage, "shader", "main", dummy_stage_callback_, dummy_includer,
|
||||
Compiler::OutputType::SpirvBinary, &errors, &total_warnings,
|
||||
&total_errors);
|
||||
errors_ = errors.str();
|
||||
EXPECT_TRUE(result) << errors_;
|
||||
return words;
|
||||
}
|
||||
|
||||
protected:
|
||||
Compiler compiler_;
|
||||
// The error string from the most recent compilation.
|
||||
std::string errors_;
|
||||
std::function<EShLanguage(std::ostream*, const shaderc_util::string_piece&)>
|
||||
dummy_stage_callback_ =
|
||||
[](std::ostream*, const shaderc_util::string_piece&) {
|
||||
return EShLangCount;
|
||||
};
|
||||
};
|
||||
|
||||
TEST_F(CompilerTest, SimpleVertexShaderCompilesSuccessfullyToBinary) {
|
||||
EXPECT_TRUE(SimpleCompilationSucceeds(kVertexShader, EShLangVertex));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, SimpleVertexShaderCompilesSuccessfullyToAssembly) {
|
||||
EXPECT_TRUE(SimpleCompilationSucceedsForOutputType(
|
||||
kVertexShader, EShLangVertex, Compiler::OutputType::SpirvAssemblyText));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, SimpleVertexShaderPreprocessesSuccessfully) {
|
||||
EXPECT_TRUE(SimpleCompilationSucceedsForOutputType(
|
||||
kVertexShader, EShLangVertex, Compiler::OutputType::PreprocessedText));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, BadVertexShaderFailsCompilation) {
|
||||
EXPECT_FALSE(SimpleCompilationSucceeds(" bogus ", EShLangVertex));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, SimpleVulkanShaderCompilesWithDefaultCompilerSettings) {
|
||||
EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, OpenGLCompatibilityProfileNotSupported) {
|
||||
const EShLanguage stage = EShLangVertex;
|
||||
|
||||
compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGLCompat);
|
||||
EXPECT_FALSE(SimpleCompilationSucceeds(kOpenGLVertexShader, stage));
|
||||
EXPECT_EQ(errors_, "error: OpenGL compatibility profile is not supported");
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, RespectTargetEnvOnOpenGLShaderForOpenGLShader) {
|
||||
const EShLanguage stage = EShLangVertex;
|
||||
|
||||
compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGL);
|
||||
EXPECT_TRUE(SimpleCompilationSucceeds(kOpenGLVertexShader, stage));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, RespectTargetEnvOnOpenGLShaderWhenDeducingStage) {
|
||||
const EShLanguage stage = EShLangVertex;
|
||||
compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGL);
|
||||
EXPECT_TRUE(
|
||||
SimpleCompilationSucceeds(kOpenGLVertexShaderDeducibleStage, stage));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, RespectTargetEnvOnVulkanShader) {
|
||||
compiler_.SetTargetEnv(Compiler::TargetEnv::Vulkan);
|
||||
EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, VulkanSpecificShaderFailsUnderOpenGLCompatibilityRules) {
|
||||
compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGLCompat);
|
||||
EXPECT_FALSE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, VulkanSpecificShaderFailsUnderOpenGLRules) {
|
||||
compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGL);
|
||||
EXPECT_FALSE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, OpenGLSpecificShaderFailsUnderDefaultRules) {
|
||||
EXPECT_FALSE(SimpleCompilationSucceeds(kOpenGLVertexShader, EShLangVertex));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest,
|
||||
OpenGLCompatibilitySpecificShaderFailsUnderOpenGLCompatibilityRules) {
|
||||
// OpenGLCompat mode now errors out. It's been deprecated for a long time.
|
||||
compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGLCompat);
|
||||
EXPECT_FALSE(SimpleCompilationSucceeds(kOpenGLCompatibilityFragShader,
|
||||
EShLangFragment));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, OpenGLCompatibilitySpecificShaderFailsUnderOpenGLRules) {
|
||||
compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGL);
|
||||
EXPECT_FALSE(SimpleCompilationSucceeds(kOpenGLCompatibilityFragShader,
|
||||
EShLangFragment));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, OpenGLCompatibilitySpecificShaderFailsUnderVulkanRules) {
|
||||
compiler_.SetTargetEnv(Compiler::TargetEnv::Vulkan);
|
||||
EXPECT_FALSE(SimpleCompilationSucceeds(kOpenGLCompatibilityFragShader,
|
||||
EShLangFragment));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, OpenGLSpecificShaderFailsUnderVulkanRules) {
|
||||
compiler_.SetTargetEnv(Compiler::TargetEnv::Vulkan);
|
||||
EXPECT_FALSE(SimpleCompilationSucceeds(kOpenGLVertexShader, EShLangVertex));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, BadTargetEnvFails) {
|
||||
compiler_.SetTargetEnv(static_cast<Compiler::TargetEnv>(32767));
|
||||
EXPECT_FALSE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
|
||||
EXPECT_THAT(errors_, HasSubstr("Invalid target client environment 32767"));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, BadTargetEnvVulkanVersionFails) {
|
||||
compiler_.SetTargetEnv(Compiler::TargetEnv::Vulkan,
|
||||
static_cast<Compiler::TargetEnvVersion>(123));
|
||||
EXPECT_FALSE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
|
||||
EXPECT_THAT(errors_,
|
||||
HasSubstr("Invalid target client version 123 for Vulkan environment 0"));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, BadTargetEnvOpenGLVersionFails) {
|
||||
compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGL,
|
||||
static_cast<Compiler::TargetEnvVersion>(123));
|
||||
EXPECT_FALSE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
|
||||
EXPECT_THAT(errors_,
|
||||
HasSubstr("Invalid target client version 123 for OpenGL environment 1"));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, SpirvTargetVersion1_0Succeeds) {
|
||||
compiler_.SetTargetSpirv(Compiler::SpirvVersion::v1_0);
|
||||
EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
|
||||
EXPECT_THAT(errors_, Eq(""));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, SpirvTargetVersion1_1Succeeds) {
|
||||
compiler_.SetTargetSpirv(Compiler::SpirvVersion::v1_1);
|
||||
EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
|
||||
EXPECT_THAT(errors_, Eq(""));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, SpirvTargetVersion1_2Succeeds) {
|
||||
compiler_.SetTargetSpirv(Compiler::SpirvVersion::v1_2);
|
||||
EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
|
||||
EXPECT_THAT(errors_, Eq(""));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, SpirvTargetVersion1_3Succeeds) {
|
||||
compiler_.SetTargetSpirv(Compiler::SpirvVersion::v1_3);
|
||||
EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
|
||||
EXPECT_THAT(errors_, Eq(""));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, SpirvTargetVersion1_4Succeeds) {
|
||||
compiler_.SetTargetSpirv(Compiler::SpirvVersion::v1_4);
|
||||
EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
|
||||
EXPECT_THAT(errors_, Eq(""));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, SpirvTargetVersion1_5Succeeds) {
|
||||
compiler_.SetTargetSpirv(Compiler::SpirvVersion::v1_5);
|
||||
EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
|
||||
EXPECT_THAT(errors_, Eq(""));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, SpirvTargetVersion1_6Succeeds) {
|
||||
compiler_.SetTargetSpirv(Compiler::SpirvVersion::v1_6);
|
||||
EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
|
||||
EXPECT_THAT(errors_, Eq(""));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, SpirvTargetBadVersionFails) {
|
||||
compiler_.SetTargetSpirv(static_cast<Compiler::SpirvVersion>(0x090900));
|
||||
EXPECT_FALSE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
|
||||
EXPECT_THAT(errors_, HasSubstr(": Unknown SPIR-V version 90900"));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, AddMacroDefinition) {
|
||||
const std::string kMinimalExpandedShader = "#version 140\nvoid E(){}";
|
||||
compiler_.AddMacroDefinition("E", 1u, "main", 4u);
|
||||
EXPECT_TRUE(SimpleCompilationSucceeds(kMinimalExpandedShader, EShLangVertex));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, AddValuelessMacroDefinitionNullPointer) {
|
||||
compiler_.AddMacroDefinition("E", 1u, nullptr, 100u);
|
||||
EXPECT_TRUE(
|
||||
SimpleCompilationSucceeds(kValuelessPredefinitionShader, EShLangVertex));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, AddValuelessMacroDefinitionZeroLength) {
|
||||
compiler_.AddMacroDefinition("E", 1u, "something", 0u);
|
||||
EXPECT_TRUE(
|
||||
SimpleCompilationSucceeds(kValuelessPredefinitionShader, EShLangVertex));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, AddMacroDefinitionNotNullTerminated) {
|
||||
const std::string kMinimalExpandedShader = "#version 140\nvoid E(){}";
|
||||
compiler_.AddMacroDefinition("EFGH", 1u, "mainnnnnn", 4u);
|
||||
EXPECT_TRUE(SimpleCompilationSucceeds(kMinimalExpandedShader, EShLangVertex));
|
||||
}
|
||||
|
||||
// A convert-string-to-vector test case consists of 1) an input string; 2) an
|
||||
// expected vector after the conversion.
|
||||
struct ConvertStringToVectorTestCase {
|
||||
std::string input_str;
|
||||
std::vector<uint32_t> expected_output_vec;
|
||||
};
|
||||
|
||||
// Test the shaderc_util::ConvertStringToVector() function. The content of the
|
||||
// input string, including the null terminator, should be packed into uint32_t
|
||||
// cells and stored in the returned vector of uint32_t. In case extra bytes are
|
||||
// required to complete the ending uint32_t element, bytes with value 0x00
|
||||
// should be used to fill the space.
|
||||
using ConvertStringToVectorTestFixture =
|
||||
testing::TestWithParam<ConvertStringToVectorTestCase>;
|
||||
|
||||
TEST_P(ConvertStringToVectorTestFixture, VariousStringSize) {
|
||||
const ConvertStringToVectorTestCase& test_case = GetParam();
|
||||
EXPECT_EQ(test_case.expected_output_vec,
|
||||
shaderc_util::ConvertStringToVector(test_case.input_str))
|
||||
<< "test_case.input_str: " << test_case.input_str << std::endl;
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
ConvertStringToVectorTest, ConvertStringToVectorTestFixture,
|
||||
testing::ValuesIn(std::vector<ConvertStringToVectorTestCase>{
|
||||
{"", {0x00000000}},
|
||||
{"1", {0x00000031}},
|
||||
{"12", {0x00003231}},
|
||||
{"123", {0x00333231}},
|
||||
{"1234", {0x34333231, 0x00000000}},
|
||||
{"12345", {0x34333231, 0x00000035}},
|
||||
{"123456", {0x34333231, 0x00003635}},
|
||||
{"1234567", {0x34333231, 0x00373635}},
|
||||
{"12345678", {0x34333231, 0x38373635, 0x00000000}},
|
||||
{"123456789", {0x34333231, 0x38373635, 0x00000039}},
|
||||
}));
|
||||
|
||||
TEST_F(CompilerTest, SetSourceLanguageToGLSLSucceeds) {
|
||||
compiler_.SetSourceLanguage(Compiler::SourceLanguage::GLSL);
|
||||
EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, SetSourceLanguageToGLSLFailsOnHLSL) {
|
||||
compiler_.SetSourceLanguage(Compiler::SourceLanguage::GLSL);
|
||||
EXPECT_FALSE(SimpleCompilationSucceeds(kHlslVertexShader, EShLangVertex));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, SetSourceLanguageToHLSLSucceeds) {
|
||||
compiler_.SetSourceLanguage(Compiler::SourceLanguage::HLSL);
|
||||
EXPECT_TRUE(SimpleCompilationSucceeds(kHlslVertexShader, EShLangVertex))
|
||||
<< errors_;
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, SetSourceLanguageToHLSLFailsOnGLSL) {
|
||||
compiler_.SetSourceLanguage(Compiler::SourceLanguage::HLSL);
|
||||
EXPECT_FALSE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, EntryPointParameterTakesEffectForHLSL) {
|
||||
compiler_.SetSourceLanguage(Compiler::SourceLanguage::HLSL);
|
||||
std::stringstream errors;
|
||||
size_t total_warnings = 0;
|
||||
size_t total_errors = 0;
|
||||
shaderc_util::GlslangInitializer initializer;
|
||||
bool result = false;
|
||||
DummyCountingIncluder dummy_includer;
|
||||
std::vector<uint32_t> words;
|
||||
std::tie(result, words, std::ignore) =
|
||||
compiler_.Compile(kHlslVertexShader, EShLangVertex, "shader",
|
||||
"EntryPoint", dummy_stage_callback_, dummy_includer,
|
||||
Compiler::OutputType::SpirvAssemblyText, &errors,
|
||||
&total_warnings, &total_errors);
|
||||
EXPECT_TRUE(result);
|
||||
std::string assembly(reinterpret_cast<char*>(words.data()));
|
||||
EXPECT_THAT(assembly,
|
||||
HasSubstr("OpEntryPoint Vertex %EntryPoint \"EntryPoint\""))
|
||||
<< assembly;
|
||||
}
|
||||
|
||||
// A test case for setting resource limits.
|
||||
struct SetLimitCase {
|
||||
Compiler::Limit limit;
|
||||
int default_value;
|
||||
int value;
|
||||
};
|
||||
|
||||
using LimitTest = testing::TestWithParam<SetLimitCase>;
|
||||
|
||||
TEST_P(LimitTest, Sample) {
|
||||
Compiler compiler;
|
||||
EXPECT_THAT(compiler.GetLimit(GetParam().limit),
|
||||
Eq(GetParam().default_value));
|
||||
compiler.SetLimit(GetParam().limit, GetParam().value);
|
||||
EXPECT_THAT(compiler.GetLimit(GetParam().limit), Eq(GetParam().value));
|
||||
}
|
||||
|
||||
#define CASE(LIMIT, DEFAULT, NEW) \
|
||||
{ Compiler::Limit::LIMIT, DEFAULT, NEW }
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
CompilerTest, LimitTest,
|
||||
// See resources.cc for the defaults.
|
||||
testing::ValuesIn(std::vector<SetLimitCase>{
|
||||
// clang-format off
|
||||
// This is just a sampling of the possible values.
|
||||
CASE(MaxLights, 8, 99),
|
||||
CASE(MaxClipPlanes, 6, 10929),
|
||||
CASE(MaxTessControlAtomicCounters, 0, 72),
|
||||
CASE(MaxSamples, 4, 8),
|
||||
// clang-format on
|
||||
}));
|
||||
#undef CASE
|
||||
|
||||
// Returns a fragment shader accessing a texture with the given
|
||||
// offset.
|
||||
std::string ShaderWithTexOffset(int offset) {
|
||||
std::ostringstream oss;
|
||||
oss << "#version 450\n"
|
||||
"layout (binding=0) uniform sampler1D tex;\n"
|
||||
"void main() { vec4 x = textureOffset(tex, 1.0, "
|
||||
<< offset << "); }\n";
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
// Ensure compilation is sensitive to limit setting. Sample just
|
||||
// two particular limits. The default minimum texel offset is -8,
|
||||
// and the default maximum texel offset is 7.
|
||||
TEST_F(CompilerTest, TexelOffsetDefaults) {
|
||||
const EShLanguage stage = EShLangFragment;
|
||||
EXPECT_FALSE(SimpleCompilationSucceeds(ShaderWithTexOffset(-9), stage));
|
||||
EXPECT_TRUE(SimpleCompilationSucceeds(ShaderWithTexOffset(-8), stage));
|
||||
EXPECT_TRUE(SimpleCompilationSucceeds(ShaderWithTexOffset(7), stage));
|
||||
EXPECT_FALSE(SimpleCompilationSucceeds(ShaderWithTexOffset(8), stage));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, TexelOffsetLowerTheMinimum) {
|
||||
const EShLanguage stage = EShLangFragment;
|
||||
compiler_.SetLimit(Compiler::Limit::MinProgramTexelOffset, -99);
|
||||
EXPECT_FALSE(SimpleCompilationSucceeds(ShaderWithTexOffset(-100), stage));
|
||||
EXPECT_TRUE(SimpleCompilationSucceeds(ShaderWithTexOffset(-99), stage));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, TexelOffsetRaiseTheMaximum) {
|
||||
const EShLanguage stage = EShLangFragment;
|
||||
compiler_.SetLimit(Compiler::Limit::MaxProgramTexelOffset, 100);
|
||||
EXPECT_TRUE(SimpleCompilationSucceeds(ShaderWithTexOffset(100), stage));
|
||||
EXPECT_FALSE(SimpleCompilationSucceeds(ShaderWithTexOffset(101), stage));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, GeneratorWordIsShadercOverGlslang) {
|
||||
const auto words = SimpleCompilationBinary(kVertexShader, EShLangVertex);
|
||||
const uint32_t shaderc_over_glslang = 13; // From SPIR-V XML Registry
|
||||
const uint32_t generator_word_index = 2; // From SPIR-V binary layout
|
||||
EXPECT_EQ(shaderc_over_glslang, words[generator_word_index] >> 16u);
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, NoBindingsAndNoAutoMapBindingsFailsCompile) {
|
||||
compiler_.SetAutoBindUniforms(false);
|
||||
EXPECT_FALSE(SimpleCompilationSucceeds(kGlslFragShaderNoExplicitBinding,
|
||||
EShLangFragment));
|
||||
EXPECT_THAT(errors_,
|
||||
HasSubstr("sampler/texture/image requires layout(binding=X)"));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, AutoMapBindingsSetsBindings) {
|
||||
compiler_.SetAutoBindUniforms(true);
|
||||
const auto words = SimpleCompilationBinary(kGlslFragShaderNoExplicitBinding,
|
||||
EShLangFragment);
|
||||
const auto disassembly = Disassemble(words);
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_tex Binding 0"))
|
||||
<< disassembly;
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_sam Binding 1"));
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_img Binding 2"));
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_imbuf Binding 3"));
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_ubo Binding 4"));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, SetBindingBaseForTextureAdjustsTextureBindingsOnly) {
|
||||
compiler_.SetAutoBindUniforms(true);
|
||||
compiler_.SetAutoBindingBase(Compiler::UniformKind::Texture, 42);
|
||||
const auto words = SimpleCompilationBinary(kGlslFragShaderNoExplicitBinding,
|
||||
EShLangFragment);
|
||||
const auto disassembly = Disassemble(words);
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_tex Binding 42"))
|
||||
<< disassembly;
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_sam Binding 0"));
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_img Binding 1"));
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_imbuf Binding 2"));
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_ubo Binding 3"));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, SetBindingBaseForSamplersAdjustsSamplerBindingsOnly) {
|
||||
compiler_.SetAutoBindUniforms(true);
|
||||
compiler_.SetAutoBindingBase(Compiler::UniformKind::Sampler, 42);
|
||||
const auto words = SimpleCompilationBinary(kGlslFragShaderNoExplicitBinding,
|
||||
EShLangFragment);
|
||||
const auto disassembly = Disassemble(words);
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_tex Binding 0"))
|
||||
<< disassembly;
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_sam Binding 42"));
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_img Binding 1"));
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_imbuf Binding 2"));
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_ubo Binding 3"));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, SetBindingBaseForImagesAdjustsImageBindingsOnly) {
|
||||
compiler_.SetAutoBindUniforms(true);
|
||||
compiler_.SetAutoBindingBase(Compiler::UniformKind::Image, 42);
|
||||
const auto words = SimpleCompilationBinary(kGlslFragShaderNoExplicitBinding,
|
||||
EShLangFragment);
|
||||
const auto disassembly = Disassemble(words);
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_tex Binding 0"))
|
||||
<< disassembly;
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_sam Binding 1"));
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_img Binding 42"));
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_imbuf Binding 43"));
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_ubo Binding 2"));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, SetBindingBaseForBufferAdjustsBufferBindingsOnly) {
|
||||
compiler_.SetAutoBindUniforms(true);
|
||||
compiler_.SetAutoBindingBase(Compiler::UniformKind::Buffer, 42);
|
||||
const auto words = SimpleCompilationBinary(kGlslFragShaderNoExplicitBinding,
|
||||
EShLangFragment);
|
||||
const auto disassembly = Disassemble(words);
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_tex Binding 0"))
|
||||
<< disassembly;
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_sam Binding 1"));
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_img Binding 2"));
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_imbuf Binding 3"));
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_ubo Binding 42"));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest,
|
||||
AutoMapBindingsSetsBindingsSetFragTextureBindingBaseCompiledAsFrag) {
|
||||
compiler_.SetAutoBindUniforms(true);
|
||||
compiler_.SetAutoBindingBaseForStage(Compiler::Stage::Fragment,
|
||||
Compiler::UniformKind::Texture, 100);
|
||||
const auto words = SimpleCompilationBinary(kGlslFragShaderNoExplicitBinding,
|
||||
EShLangFragment);
|
||||
const auto disassembly = Disassemble(words);
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_tex Binding 100"))
|
||||
<< disassembly;
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_sam Binding 0"));
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_img Binding 1"));
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_imbuf Binding 2"));
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_ubo Binding 3"));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest,
|
||||
AutoMapBindingsSetsBindingsSetFragImageBindingBaseCompiledAsVert) {
|
||||
compiler_.SetAutoBindUniforms(true);
|
||||
// This is ignored because we're compiling the shader as a vertex shader, not
|
||||
// as a fragment shader.
|
||||
compiler_.SetAutoBindingBaseForStage(Compiler::Stage::Fragment,
|
||||
Compiler::UniformKind::Image, 100);
|
||||
const auto words =
|
||||
SimpleCompilationBinary(kGlslFragShaderNoExplicitBinding, EShLangVertex);
|
||||
const auto disassembly = Disassemble(words);
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_tex Binding 0"))
|
||||
<< disassembly;
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_sam Binding 1"));
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_img Binding 2"));
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_imbuf Binding 3"));
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_ubo Binding 4"));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, NoAutoMapLocationsFailsCompilationOnOpenGLShader) {
|
||||
compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGL);
|
||||
compiler_.SetAutoMapLocations(false);
|
||||
|
||||
const auto words =
|
||||
SimpleCompilationBinary(kGlslVertShaderExplicitLocation, EShLangVertex);
|
||||
const auto disassembly = Disassemble(words);
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_mat Location 10"))
|
||||
<< disassembly;
|
||||
|
||||
EXPECT_FALSE(SimpleCompilationSucceeds(kGlslVertShaderNoExplicitLocation,
|
||||
EShLangVertex));
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, AutoMapLocationsSetsLocationsOnOpenGLShader) {
|
||||
compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGL);
|
||||
compiler_.SetAutoMapLocations(true);
|
||||
|
||||
const auto words_no_auto =
|
||||
SimpleCompilationBinary(kGlslVertShaderExplicitLocation, EShLangVertex);
|
||||
const auto disassembly_no_auto = Disassemble(words_no_auto);
|
||||
EXPECT_THAT(disassembly_no_auto, HasSubstr("OpDecorate %my_mat Location 10"))
|
||||
<< disassembly_no_auto;
|
||||
|
||||
const auto words_auto =
|
||||
SimpleCompilationBinary(kGlslVertShaderNoExplicitLocation, EShLangVertex);
|
||||
const auto disassembly_auto = Disassemble(words_auto);
|
||||
EXPECT_THAT(disassembly_auto, HasSubstr("OpDecorate %my_mat Location 0"))
|
||||
<< disassembly_auto;
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, EmitMessageTextOnlyOnce) {
|
||||
// Emit a warning by compiling a shader without a default entry point name.
|
||||
// The warning should only be emitted once even though we do parsing, linking,
|
||||
// and IO mapping.
|
||||
Compiler c;
|
||||
std::stringstream errors;
|
||||
size_t total_warnings = 0;
|
||||
size_t total_errors = 0;
|
||||
shaderc_util::GlslangInitializer initializer;
|
||||
bool result = false;
|
||||
DummyCountingIncluder dummy_includer;
|
||||
std::tie(result, std::ignore, std::ignore) = c.Compile(
|
||||
"#version 150\nvoid MyEntryPoint(){}", EShLangVertex, "shader", "",
|
||||
dummy_stage_callback_, dummy_includer, Compiler::OutputType::SpirvBinary,
|
||||
&errors, &total_warnings, &total_errors);
|
||||
const std::string errs = errors.str();
|
||||
EXPECT_THAT(errs, Eq("shader: error: Linking vertex stage: Missing entry "
|
||||
"point: Each stage requires one entry point\n"))
|
||||
<< errs;
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, GlslDefaultPackingUsed) {
|
||||
const auto words =
|
||||
SimpleCompilationBinary(kGlslShaderWeirdPacking, EShLangVertex);
|
||||
const auto disassembly = Disassemble(words);
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpMemberDecorate %B 1 Offset 16"))
|
||||
<< disassembly;
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, HlslOffsetsOptionDisableRespected) {
|
||||
compiler_.SetHlslOffsets(false);
|
||||
const auto words =
|
||||
SimpleCompilationBinary(kGlslShaderWeirdPacking, EShLangVertex);
|
||||
const auto disassembly = Disassemble(words);
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpMemberDecorate %B 1 Offset 16"))
|
||||
<< disassembly;
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, HlslOffsetsOptionEnableRespected) {
|
||||
compiler_.SetHlslOffsets(true);
|
||||
const auto words =
|
||||
SimpleCompilationBinary(kGlslShaderWeirdPacking, EShLangVertex);
|
||||
const auto disassembly = Disassemble(words);
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpMemberDecorate %B 1 Offset 4"))
|
||||
<< disassembly;
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, HlslLegalizationEnabledNoSizeOpt) {
|
||||
compiler_.SetSourceLanguage(Compiler::SourceLanguage::HLSL);
|
||||
const auto words =
|
||||
SimpleCompilationBinary(kHlslShaderForLegalizationTest, EShLangFragment);
|
||||
const auto disassembly = Disassemble(words);
|
||||
EXPECT_THAT(disassembly, Not(HasSubstr("OpFunctionCall"))) << disassembly;
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpName")) << disassembly;
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, HlslLegalizationEnabledWithSizeOpt) {
|
||||
compiler_.SetSourceLanguage(Compiler::SourceLanguage::HLSL);
|
||||
compiler_.SetOptimizationLevel(Compiler::OptimizationLevel::Size);
|
||||
const auto words =
|
||||
SimpleCompilationBinary(kHlslShaderForLegalizationTest, EShLangFragment);
|
||||
const auto disassembly = Disassemble(words);
|
||||
EXPECT_THAT(disassembly, Not(HasSubstr("OpFunctionCall"))) << disassembly;
|
||||
EXPECT_THAT(disassembly, Not(HasSubstr("OpName"))) << disassembly;
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, HlslLegalizationDisabled) {
|
||||
compiler_.SetSourceLanguage(Compiler::SourceLanguage::HLSL);
|
||||
compiler_.EnableHlslLegalization(false);
|
||||
const auto words =
|
||||
SimpleCompilationBinary(kHlslShaderForLegalizationTest, EShLangFragment);
|
||||
const auto disassembly = Disassemble(words);
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpFunctionCall")) << disassembly;
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, HlslFunctionality1Enabled) {
|
||||
compiler_.SetSourceLanguage(Compiler::SourceLanguage::HLSL);
|
||||
compiler_.EnableHlslFunctionality1(true);
|
||||
compiler_.SetAutoBindUniforms(true); // Counter variable needs a binding.
|
||||
const auto words =
|
||||
SimpleCompilationBinary(kHlslShaderWithCounterBuffer, EShLangFragment);
|
||||
const auto disassembly = Disassemble(words);
|
||||
EXPECT_THAT(disassembly,
|
||||
HasSubstr("OpExtension \"SPV_GOOGLE_hlsl_functionality1\""))
|
||||
<< disassembly;
|
||||
EXPECT_THAT(disassembly,
|
||||
HasSubstr("OpDecorateString %_entryPointOutput "
|
||||
"UserSemantic \"SV_TARGET0\""))
|
||||
<< disassembly;
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, RelaxedVulkanRulesEnabled) {
|
||||
compiler_.SetSourceLanguage(Compiler::SourceLanguage::GLSL);
|
||||
compiler_.SetAutoBindUniforms(true); // Uniform variable needs a binding
|
||||
compiler_.SetVulkanRulesRelaxed(true);
|
||||
const auto words =
|
||||
SimpleCompilationBinary(kGlslFragShaderOpaqueUniforms, EShLangFragment);
|
||||
const auto disassembly = Disassemble(words);
|
||||
EXPECT_THAT(disassembly,
|
||||
HasSubstr("OpMemberName %gl_DefaultUniformBlock 0 \"a\""))
|
||||
<< disassembly;
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, ClampMapsToFClampByDefault) {
|
||||
const auto words =
|
||||
SimpleCompilationBinary(kGlslShaderWithClamp, EShLangFragment);
|
||||
const auto disassembly = Disassemble(words);
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpExtInst %v4float %1 FClamp"))
|
||||
<< disassembly;
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, ClampMapsToFClampWithNanClamp) {
|
||||
compiler_.SetNanClamp(true);
|
||||
const auto words =
|
||||
SimpleCompilationBinary(kGlslShaderWithClamp, EShLangFragment);
|
||||
const auto disassembly = Disassemble(words);
|
||||
EXPECT_THAT(disassembly, HasSubstr("OpExtInst %v4float %1 NClamp"))
|
||||
<< disassembly;
|
||||
}
|
||||
|
||||
// A test coase for Glslang
|
||||
// expected vector after the conversion.
|
||||
struct GetGlslangClientInfoCase {
|
||||
std::string prefix;
|
||||
Compiler::TargetEnv env;
|
||||
Compiler::TargetEnvVersion env_version;
|
||||
Compiler::SpirvVersion spv_version;
|
||||
bool spv_forced;
|
||||
// Expected results. The error field is matched as a substring.
|
||||
GlslangClientInfo expected;
|
||||
};
|
||||
|
||||
// Test the shaderc_util::GetGlslangClientInfo function.
|
||||
using GetGlslangClientInfoTest =
|
||||
testing::TestWithParam<GetGlslangClientInfoCase>;
|
||||
|
||||
TEST_P(GetGlslangClientInfoTest, Sample) {
|
||||
const auto& c = GetParam();
|
||||
const auto& expected = c.expected;
|
||||
auto result = shaderc_util::GetGlslangClientInfo(
|
||||
c.prefix, c.env, c.env_version, c.spv_version, c.spv_forced);
|
||||
|
||||
EXPECT_THAT(result.error.empty(), Eq(expected.error.empty()));
|
||||
if (result.error.empty()) {
|
||||
EXPECT_THAT(result.client, Eq(expected.client));
|
||||
EXPECT_THAT(result.client_version, Eq(expected.client_version));
|
||||
EXPECT_THAT(result.target_language, Eq(expected.target_language));
|
||||
EXPECT_THAT(result.target_language_version,
|
||||
Eq(expected.target_language_version));
|
||||
} else {
|
||||
EXPECT_THAT(result.error, HasSubstr(expected.error));
|
||||
}
|
||||
}
|
||||
|
||||
#define CASE_VK(VKVER, SPVVER) \
|
||||
"", Compiler::TargetEnv::Vulkan, Compiler::TargetEnvVersion::Vulkan_##VKVER, \
|
||||
Compiler::SpirvVersion::v##SPVVER
|
||||
|
||||
#define BADCASE_VK(STR, VKVER, SPVVER) \
|
||||
STR, Compiler::TargetEnv::Vulkan, \
|
||||
static_cast<Compiler::TargetEnvVersion>(VKVER), \
|
||||
static_cast<Compiler::SpirvVersion>(SPVVER)
|
||||
|
||||
#define CASE_GL(GLVER, SPVVER) \
|
||||
"", Compiler::TargetEnv::OpenGL, Compiler::TargetEnvVersion::OpenGL_##GLVER, \
|
||||
Compiler::SpirvVersion::v##SPVVER
|
||||
|
||||
#define BADCASE_GL(STR, GLVER, SPVVER) \
|
||||
STR, Compiler::TargetEnv::OpenGL, \
|
||||
static_cast<Compiler::TargetEnvVersion>(GLVER), \
|
||||
static_cast<Compiler::SpirvVersion>(SPVVER)
|
||||
|
||||
#define GCASE_VK(STR, VKVER, SPVVER) \
|
||||
shaderc_util::GlslangClientInfo { \
|
||||
std::string(STR), glslang::EShClientVulkan, \
|
||||
glslang::EShTargetVulkan_##VKVER, glslang::EShTargetSpv, \
|
||||
glslang::EShTargetSpv_##SPVVER \
|
||||
}
|
||||
|
||||
#define GCASE_GL(STR, GLVER, SPVVER) \
|
||||
shaderc_util::GlslangClientInfo { \
|
||||
std::string(STR), glslang::EShClientOpenGL, \
|
||||
glslang::EShTargetOpenGL_##GLVER, glslang::EShTargetSpv, \
|
||||
glslang::EShTargetSpv_##SPVVER \
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
UnforcedSpirvSuccess, GetGlslangClientInfoTest,
|
||||
testing::ValuesIn(std::vector<GetGlslangClientInfoCase>{
|
||||
// Unforced SPIR-V version. Success cases.
|
||||
{CASE_VK(1_0, 1_4), false, GCASE_VK("", 1_0, 1_0)},
|
||||
{CASE_VK(1_1, 1_4), false, GCASE_VK("", 1_1, 1_3)},
|
||||
{CASE_GL(4_5, 1_4), false, GCASE_GL("", 450, 1_0)},
|
||||
}));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
ForcedSpirvSuccess, GetGlslangClientInfoTest,
|
||||
testing::ValuesIn(std::vector<GetGlslangClientInfoCase>{
|
||||
// Forced SPIR-V version. Success cases.
|
||||
{CASE_VK(1_0, 1_0), true, GCASE_VK("", 1_0, 1_0)},
|
||||
{CASE_VK(1_0, 1_1), true, GCASE_VK("", 1_0, 1_1)},
|
||||
{CASE_VK(1_0, 1_2), true, GCASE_VK("", 1_0, 1_2)},
|
||||
{CASE_VK(1_0, 1_3), true, GCASE_VK("", 1_0, 1_3)},
|
||||
{CASE_VK(1_1, 1_0), true, GCASE_VK("", 1_1, 1_0)},
|
||||
{CASE_VK(1_1, 1_1), true, GCASE_VK("", 1_1, 1_1)},
|
||||
{CASE_VK(1_1, 1_2), true, GCASE_VK("", 1_1, 1_2)},
|
||||
{CASE_VK(1_1, 1_3), true, GCASE_VK("", 1_1, 1_3)},
|
||||
{CASE_GL(4_5, 1_0), true, GCASE_GL("", 450, 1_0)},
|
||||
{CASE_GL(4_5, 1_1), true, GCASE_GL("", 450, 1_1)},
|
||||
{CASE_GL(4_5, 1_2), true, GCASE_GL("", 450, 1_2)},
|
||||
}));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
Failure, GetGlslangClientInfoTest,
|
||||
testing::ValuesIn(std::vector<GetGlslangClientInfoCase>{
|
||||
// Failure cases.
|
||||
{BADCASE_VK("foo", 999, Compiler::SpirvVersion::v1_0), false,
|
||||
GCASE_VK("error:foo: Invalid target client version 999 for Vulkan "
|
||||
"environment 0",
|
||||
1_0, 1_0)},
|
||||
{BADCASE_GL("foo", 999, Compiler::SpirvVersion::v1_0), false,
|
||||
GCASE_GL("error:foo: Invalid target client version 999 for OpenGL "
|
||||
"environment 1",
|
||||
450, 1_0)},
|
||||
// For bad SPIR-V versions, have to force=true to make it pay attention.
|
||||
{BADCASE_VK("foo", Compiler::TargetEnvVersion::Vulkan_1_0, 999), true,
|
||||
GCASE_VK("error:foo: Unknown SPIR-V version 3e7", 1_0, 1_0)},
|
||||
{BADCASE_GL("foo", Compiler::TargetEnvVersion::OpenGL_4_5, 999), true,
|
||||
GCASE_GL("error:foo: Unknown SPIR-V version 3e7", 450, 1_0)},
|
||||
}));
|
||||
|
||||
#undef CASE_VK
|
||||
#undef CASE_GL
|
||||
#undef BADCASE_VK
|
||||
#undef BADCASE_GL
|
||||
#undef GCASE_VK
|
||||
#undef GCASE_GL
|
||||
} // anonymous namespace
|
||||
93
3rdparty/shaderc/libshaderc_util/src/counting_includer_test.cc
vendored
Normal file
93
3rdparty/shaderc/libshaderc_util/src/counting_includer_test.cc
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
// Copyright 2015 The Shaderc Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "libshaderc_util/counting_includer.h"
|
||||
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
namespace {
|
||||
|
||||
// A trivial implementation of CountingIncluder's virtual methods, so tests can
|
||||
// instantiate.
|
||||
class ConcreteCountingIncluder : public shaderc_util::CountingIncluder {
|
||||
public:
|
||||
using IncludeResult = glslang::TShader::Includer::IncludeResult;
|
||||
~ConcreteCountingIncluder() {
|
||||
// Avoid leaks.
|
||||
for (auto result : results_) {
|
||||
release_delegate(result);
|
||||
}
|
||||
}
|
||||
virtual IncludeResult* include_delegate(
|
||||
const char* requested, const char* requestor, IncludeType,
|
||||
size_t) override {
|
||||
const char kError[] = "Unexpected #include";
|
||||
results_.push_back(new IncludeResult{"", kError, strlen(kError), nullptr});
|
||||
return results_.back();
|
||||
}
|
||||
virtual void release_delegate(IncludeResult* include_result) override {
|
||||
delete include_result;
|
||||
}
|
||||
|
||||
private:
|
||||
// All the results we've returned so far.
|
||||
std::vector<IncludeResult*> results_;
|
||||
};
|
||||
|
||||
TEST(CountingIncluderTest, InitialCount) {
|
||||
EXPECT_EQ(0, ConcreteCountingIncluder().num_include_directives());
|
||||
}
|
||||
|
||||
TEST(CountingIncluderTest, OneIncludeLocal) {
|
||||
ConcreteCountingIncluder includer;
|
||||
includer.includeLocal("random file name", "from me", 0);
|
||||
EXPECT_EQ(1, includer.num_include_directives());
|
||||
}
|
||||
|
||||
TEST(CountingIncluderTest, TwoIncludesAnyIncludeType) {
|
||||
ConcreteCountingIncluder includer;
|
||||
includer.includeSystem("name1", "from me", 0);
|
||||
includer.includeLocal("name2", "me", 0);
|
||||
EXPECT_EQ(2, includer.num_include_directives());
|
||||
}
|
||||
|
||||
TEST(CountingIncluderTest, ManyIncludes) {
|
||||
ConcreteCountingIncluder includer;
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
includer.includeLocal("filename", "from me", i);
|
||||
includer.includeSystem("filename", "from me", i);
|
||||
}
|
||||
EXPECT_EQ(200, includer.num_include_directives());
|
||||
}
|
||||
|
||||
#ifndef SHADERC_DISABLE_THREADED_TESTS
|
||||
TEST(CountingIncluderTest, ThreadedIncludes) {
|
||||
ConcreteCountingIncluder includer;
|
||||
std::thread t1(
|
||||
[&includer]() { includer.includeLocal("name1", "me", 0); });
|
||||
std::thread t2(
|
||||
[&includer]() { includer.includeSystem("name2", "me", 1); });
|
||||
std::thread t3(
|
||||
[&includer]() { includer.includeLocal("name3", "me", 2); });
|
||||
t1.join();
|
||||
t2.join();
|
||||
t3.join();
|
||||
EXPECT_EQ(3, includer.num_include_directives());
|
||||
}
|
||||
#endif // SHADERC_DISABLE_THREADED_TESTS
|
||||
|
||||
} // anonymous namespace
|
||||
25
3rdparty/shaderc/libshaderc_util/src/death_test.h
vendored
Normal file
25
3rdparty/shaderc/libshaderc_util/src/death_test.h
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright 2015 The Shaderc Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBSHADERC_UTIL_SRC_DEATH_TEST_H
|
||||
#define LIBSHADERC_UTIL_SRC_DEATH_TEST_H
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define EXPECT_DEBUG_DEATH_IF_SUPPORTED(statement, regexp)
|
||||
#else
|
||||
#define EXPECT_DEBUG_DEATH_IF_SUPPORTED(statement, regexp) \
|
||||
EXPECT_DEATH_IF_SUPPORTED(statement, regexp)
|
||||
#endif
|
||||
|
||||
#endif // LIBSHADERC_UTIL_SRC_DEATH_TEST_H
|
||||
71
3rdparty/shaderc/libshaderc_util/src/file_finder.cc
vendored
Normal file
71
3rdparty/shaderc/libshaderc_util/src/file_finder.cc
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
// Copyright 2015 The Shaderc Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "libshaderc_util/file_finder.h"
|
||||
#include "libshaderc_util/string_piece.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <fstream>
|
||||
#include <ios>
|
||||
|
||||
namespace {
|
||||
|
||||
// Returns "" if path is empty or ends in '/'. Otherwise, returns "/".
|
||||
std::string MaybeSlash(const shaderc_util::string_piece& path) {
|
||||
return (path.empty() || path.back() == '/') ? "" : "/";
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace shaderc_util {
|
||||
|
||||
std::string FileFinder::FindReadableFilepath(
|
||||
const std::string& filename) const {
|
||||
assert(!filename.empty());
|
||||
static const auto for_reading = std::ios_base::in;
|
||||
std::filebuf opener;
|
||||
for (const auto& prefix : search_path_) {
|
||||
const std::string prefixed_filename =
|
||||
prefix + MaybeSlash(prefix) + filename;
|
||||
if (opener.open(prefixed_filename, for_reading)) return prefixed_filename;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string FileFinder::FindRelativeReadableFilepath(
|
||||
const std::string& requesting_file, const std::string& filename) const {
|
||||
assert(!filename.empty());
|
||||
|
||||
string_piece dir_name(requesting_file);
|
||||
|
||||
size_t last_slash = requesting_file.find_last_of("/\\");
|
||||
if (last_slash != std::string::npos) {
|
||||
dir_name = string_piece(requesting_file.c_str(),
|
||||
requesting_file.c_str() + last_slash);
|
||||
}
|
||||
|
||||
if (dir_name.size() == requesting_file.size()) {
|
||||
dir_name.clear();
|
||||
}
|
||||
|
||||
static const auto for_reading = std::ios_base::in;
|
||||
std::filebuf opener;
|
||||
const std::string relative_filename =
|
||||
dir_name.str() + MaybeSlash(dir_name) + filename;
|
||||
if (opener.open(relative_filename, for_reading)) return relative_filename;
|
||||
|
||||
return FindReadableFilepath(filename);
|
||||
}
|
||||
|
||||
} // namespace shaderc_util
|
||||
146
3rdparty/shaderc/libshaderc_util/src/file_finder_test.cc
vendored
Normal file
146
3rdparty/shaderc/libshaderc_util/src/file_finder_test.cc
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
// Copyright 2015 The Shaderc Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "libshaderc_util/file_finder.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
// We need getcwd
|
||||
#if WIN32
|
||||
#include <direct.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "death_test.h"
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
using shaderc_util::FileFinder;
|
||||
|
||||
// Returns the absolute path of the current working directory.
|
||||
std::string GetCurrentDir() {
|
||||
// Provide generous space to write the path.
|
||||
char buf[1000];
|
||||
#if WIN32
|
||||
return _getcwd(buf, sizeof(buf));
|
||||
#else
|
||||
return getcwd(buf, sizeof(buf));
|
||||
#endif
|
||||
}
|
||||
|
||||
class FileFinderTest : public testing::Test {
|
||||
protected:
|
||||
FileFinder finder;
|
||||
// Absolute path of the current working directory.
|
||||
const std::string current_dir = GetCurrentDir();
|
||||
};
|
||||
|
||||
TEST_F(FileFinderTest, PathStartsEmpty) {
|
||||
EXPECT_TRUE(FileFinder().search_path().empty());
|
||||
}
|
||||
|
||||
TEST_F(FileFinderTest, EmptyPath) {
|
||||
finder.search_path().clear();
|
||||
EXPECT_EQ("", finder.FindReadableFilepath("include_file.1"));
|
||||
}
|
||||
|
||||
TEST_F(FileFinderTest, EmptyStringInPath) {
|
||||
finder.search_path() = {""};
|
||||
EXPECT_EQ("include_file.1", finder.FindReadableFilepath("include_file.1"));
|
||||
EXPECT_EQ("dir/subdir/include_file.2",
|
||||
finder.FindReadableFilepath("dir/subdir/include_file.2"));
|
||||
}
|
||||
|
||||
TEST_F(FileFinderTest, SimplePath) {
|
||||
finder.search_path() = {"dir"};
|
||||
EXPECT_EQ("dir/subdir/include_file.2",
|
||||
finder.FindReadableFilepath("subdir/include_file.2"));
|
||||
}
|
||||
|
||||
TEST_F(FileFinderTest, PathEndsInSlash) {
|
||||
finder.search_path() = {"dir/"};
|
||||
EXPECT_EQ("dir/subdir/include_file.2",
|
||||
finder.FindReadableFilepath("subdir/include_file.2"));
|
||||
}
|
||||
|
||||
TEST_F(FileFinderTest, ParentDir) {
|
||||
finder.search_path() = {"dir"};
|
||||
EXPECT_EQ("dir/../include_file.1",
|
||||
finder.FindReadableFilepath("../include_file.1"));
|
||||
}
|
||||
|
||||
TEST_F(FileFinderTest, EntirePathIsActive) {
|
||||
finder.search_path() = {"", "dir/subdir/"};
|
||||
EXPECT_EQ("include_file.1", finder.FindReadableFilepath("include_file.1"));
|
||||
EXPECT_EQ("dir/subdir/include_file.2",
|
||||
finder.FindReadableFilepath("include_file.2"));
|
||||
}
|
||||
|
||||
TEST_F(FileFinderTest, NonExistingFile) {
|
||||
finder.search_path() = {"", "dir/subdir/"};
|
||||
EXPECT_EQ("", finder.FindReadableFilepath("garbage.xyxyxyxyxyxz"));
|
||||
}
|
||||
|
||||
TEST_F(FileFinderTest, FirstHitReturned) {
|
||||
finder.search_path() = {".", "", "dir/../"};
|
||||
EXPECT_EQ("./include_file.1", finder.FindReadableFilepath("include_file.1"));
|
||||
}
|
||||
|
||||
TEST_F(FileFinderTest, IrrelevantPaths) {
|
||||
finder.search_path() = {".", "garbage.xyxyxyxyxyz", "dir/../"};
|
||||
EXPECT_EQ("", finder.FindReadableFilepath("include_file.2"));
|
||||
finder.search_path().push_back("dir/subdir");
|
||||
EXPECT_EQ("dir/subdir/include_file.2",
|
||||
finder.FindReadableFilepath("include_file.2"));
|
||||
}
|
||||
|
||||
TEST_F(FileFinderTest, CurrentDirectory) {
|
||||
ASSERT_GE(current_dir.size(), 0u);
|
||||
// Either the directory should start with / (if we are on Linux),
|
||||
// Or it should beither X:/ or X:\ or // (if we are on Windows).
|
||||
ASSERT_TRUE(current_dir.front() == '\\' || current_dir.front() == '/' ||
|
||||
(current_dir.size() >= 3u && current_dir[1] == ':' &&
|
||||
(current_dir[2] == '\\' || current_dir[2] == '/')));
|
||||
}
|
||||
|
||||
TEST_F(FileFinderTest, AbsolutePath) {
|
||||
ASSERT_NE('/', current_dir.back());
|
||||
finder.search_path() = {current_dir};
|
||||
EXPECT_EQ(current_dir + "/include_file.1",
|
||||
finder.FindReadableFilepath("include_file.1"));
|
||||
EXPECT_EQ(current_dir + "/dir/subdir/include_file.2",
|
||||
finder.FindReadableFilepath("dir/subdir/include_file.2"));
|
||||
}
|
||||
|
||||
TEST_F(FileFinderTest, AbsoluteFilename) {
|
||||
ASSERT_NE('/', current_dir.back());
|
||||
|
||||
finder.search_path() = {""};
|
||||
const std::string absolute_file1 = current_dir + "/include_file.1";
|
||||
EXPECT_EQ(absolute_file1, finder.FindReadableFilepath(absolute_file1));
|
||||
EXPECT_EQ("", finder.FindReadableFilepath("/dir/subdir/include_file.2"));
|
||||
|
||||
finder.search_path().push_back(".");
|
||||
EXPECT_EQ(".//dir/subdir/include_file.2",
|
||||
finder.FindReadableFilepath("/dir/subdir/include_file.2"));
|
||||
}
|
||||
|
||||
TEST(FileFinderDeathTest, EmptyFilename) {
|
||||
EXPECT_DEBUG_DEATH_IF_SUPPORTED(FileFinder().FindReadableFilepath(""),
|
||||
"Assertion");
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
105
3rdparty/shaderc/libshaderc_util/src/format_test.cc
vendored
Normal file
105
3rdparty/shaderc/libshaderc_util/src/format_test.cc
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
// Copyright 2015 The Shaderc Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "libshaderc_util/format.h"
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace {
|
||||
|
||||
using testing::AllOf;
|
||||
using testing::HasSubstr;
|
||||
using testing::IsEmpty;
|
||||
|
||||
class FormatMap : public testing::Test {
|
||||
public:
|
||||
FormatMap()
|
||||
: map1({{"one", 1}}),
|
||||
umap1({map1.begin(), map1.end()}),
|
||||
map8({{1, "one"},
|
||||
{2, "two"},
|
||||
{3, "three"},
|
||||
{4, "four"},
|
||||
{5, "five"},
|
||||
{6, "six"},
|
||||
{7, "seven"},
|
||||
{8, "eight"}}),
|
||||
umap8({map8.begin(), map8.end()}),
|
||||
mmap({{1, 100}, {1, 200}, {2, 100}, {2, 200}}),
|
||||
ummap({mmap.begin(), mmap.end()}) {}
|
||||
|
||||
protected:
|
||||
std::map<int, int> empty_map;
|
||||
std::unordered_map<int, int> empty_umap;
|
||||
std::map<std::string, int> map1;
|
||||
std::unordered_map<std::string, int> umap1;
|
||||
std::map<int, std::string> map8;
|
||||
std::unordered_map<int, std::string> umap8;
|
||||
std::multimap<int, int> mmap;
|
||||
std::unordered_multimap<int, int> ummap;
|
||||
};
|
||||
|
||||
TEST_F(FormatMap, EmptyMap) {
|
||||
EXPECT_THAT(shaderc_util::format(empty_map, "pre", "in", "post"), IsEmpty());
|
||||
EXPECT_THAT(shaderc_util::format(empty_umap, "pre", "in", "post"), IsEmpty());
|
||||
}
|
||||
|
||||
TEST_F(FormatMap, SingleEntry) {
|
||||
EXPECT_EQ("PREoneIN1POST", shaderc_util::format(map1, "PRE", "IN", "POST"));
|
||||
EXPECT_EQ("PREoneIN1POST", shaderc_util::format(umap1, "PRE", "IN", "POST"));
|
||||
}
|
||||
|
||||
TEST_F(FormatMap, EmptyPrefix) {
|
||||
EXPECT_EQ("oneIN1POST", shaderc_util::format(map1, "", "IN", "POST"));
|
||||
EXPECT_EQ("oneIN1POST", shaderc_util::format(umap1, "", "IN", "POST"));
|
||||
}
|
||||
|
||||
TEST_F(FormatMap, EmptyInfix) {
|
||||
EXPECT_EQ("PREone1POST", shaderc_util::format(map1, "PRE", "", "POST"));
|
||||
EXPECT_EQ("PREone1POST", shaderc_util::format(umap1, "PRE", "", "POST"));
|
||||
}
|
||||
|
||||
TEST_F(FormatMap, EmptyPostfix) {
|
||||
EXPECT_EQ("PREoneIN1", shaderc_util::format(map1, "PRE", "IN", ""));
|
||||
EXPECT_EQ("PREoneIN1", shaderc_util::format(umap1, "PRE", "IN", ""));
|
||||
}
|
||||
|
||||
TEST_F(FormatMap, LargerMap) {
|
||||
const std::string result = shaderc_util::format(map8, "", "", "\n"),
|
||||
uresult = shaderc_util::format(umap8, "", "", "\n");
|
||||
auto has_all =
|
||||
AllOf(HasSubstr("1one\n"), HasSubstr("2two\n"), HasSubstr("3three\n"),
|
||||
HasSubstr("4four\n"), HasSubstr("5five\n"), HasSubstr("6six\n"),
|
||||
HasSubstr("7seven\n"), HasSubstr("8eight\n"));
|
||||
EXPECT_THAT(result, has_all);
|
||||
EXPECT_EQ(48u, result.size());
|
||||
EXPECT_THAT(uresult, has_all);
|
||||
EXPECT_EQ(48u, uresult.size());
|
||||
}
|
||||
|
||||
TEST_F(FormatMap, Multimap) {
|
||||
const std::string result = shaderc_util::format(mmap, " ", "&", ""),
|
||||
uresult = shaderc_util::format(ummap, " ", "&", "");
|
||||
auto has_all = AllOf(HasSubstr(" 1&100"), HasSubstr(" 1&200"),
|
||||
HasSubstr(" 2&100"), HasSubstr(" 2&200"));
|
||||
EXPECT_THAT(result, has_all);
|
||||
EXPECT_EQ(4 * 6u, result.size());
|
||||
EXPECT_THAT(uresult, has_all);
|
||||
EXPECT_EQ(4 * 6u, uresult.size());
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
146
3rdparty/shaderc/libshaderc_util/src/io_shaderc.cc
vendored
Normal file
146
3rdparty/shaderc/libshaderc_util/src/io_shaderc.cc
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
// Copyright 2015 The Shaderc Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "libshaderc_util/io_shaderc.h"
|
||||
|
||||
#include "libshaderc_util/universal_unistd.h"
|
||||
|
||||
#if _WIN32
|
||||
// Need _fileno from stdio.h
|
||||
// Need _O_BINARY and _O_TEXT from fcntl.h
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
namespace {
|
||||
|
||||
// Outputs a descriptive message for errno_value to cerr.
|
||||
// This may be truncated to 1023 bytes on certain platforms.
|
||||
void OutputFileErrorMessage(int errno_value) {
|
||||
#ifdef _MSC_VER
|
||||
// If the error message is more than 1023 bytes it will be truncated.
|
||||
char buffer[1024];
|
||||
strerror_s(buffer, errno_value);
|
||||
std::cerr << ": " << buffer << std::endl;
|
||||
#else
|
||||
std::cerr << ": " << strerror(errno_value) << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace shaderc_util {
|
||||
|
||||
bool IsAbsolutePath(const std::string& path) {
|
||||
if (path.empty()) return false;
|
||||
// Unix-like OS: /path/to/file
|
||||
if (path.front() == '/') return true;
|
||||
// Windows: \\server\user\file
|
||||
if (path.size() > 1 && path[0] == '\\' && path[1] == '\\') {
|
||||
return true;
|
||||
}
|
||||
// Windows: X:\path\to\file
|
||||
if (path.size() > 2 && ::isalpha(path[0]) && path[1] == ':' &&
|
||||
path[2] == '\\') {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string GetBaseFileName(const std::string& file_path) {
|
||||
size_t loc_slash = file_path.find_last_of("/\\");
|
||||
std::string base_name =
|
||||
file_path.substr((loc_slash == std::string::npos ? -1 : loc_slash) + 1);
|
||||
if (base_name == ".." || base_name == ".") {
|
||||
base_name = "";
|
||||
}
|
||||
return base_name;
|
||||
}
|
||||
|
||||
bool ReadFile(const std::string& input_file_name,
|
||||
std::vector<char>* input_data) {
|
||||
std::istream* stream = &std::cin;
|
||||
std::ifstream input_file;
|
||||
if (input_file_name != "-") {
|
||||
input_file.open(input_file_name, std::ios_base::binary);
|
||||
stream = &input_file;
|
||||
if (input_file.fail()) {
|
||||
std::cerr << "glslc: error: cannot open input file: '" << input_file_name
|
||||
<< "'";
|
||||
if (access(input_file_name.c_str(), R_OK) != 0) {
|
||||
OutputFileErrorMessage(errno);
|
||||
return false;
|
||||
}
|
||||
std::cerr << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
*input_data = std::vector<char>((std::istreambuf_iterator<char>(*stream)),
|
||||
std::istreambuf_iterator<char>());
|
||||
return true;
|
||||
}
|
||||
|
||||
std::ostream* GetOutputStream(const string_piece& output_filename,
|
||||
std::ofstream* file_stream, std::ostream* err) {
|
||||
std::ostream* stream = &std::cout;
|
||||
if (output_filename != "-") {
|
||||
file_stream->open(output_filename.str(), std::ios_base::binary);
|
||||
stream = file_stream;
|
||||
if (file_stream->fail()) {
|
||||
*err << "glslc: error: cannot open output file: '" << output_filename
|
||||
<< "'";
|
||||
if (access(output_filename.str().c_str(), W_OK) != 0) {
|
||||
OutputFileErrorMessage(errno);
|
||||
return nullptr;
|
||||
}
|
||||
std::cerr << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
bool WriteFile(std::ostream* stream, const string_piece& output_data) {
|
||||
if (output_data.size() > 0) {
|
||||
stream->write(output_data.data(), output_data.size());
|
||||
if (!stream->good()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
stream->flush();
|
||||
return true;
|
||||
}
|
||||
|
||||
void FlushAndSetBinaryModeOnStdout() {
|
||||
std::fflush(stdout);
|
||||
#if _WIN32
|
||||
_setmode(_fileno(stdout), _O_BINARY);
|
||||
#endif
|
||||
}
|
||||
|
||||
void FlushAndSetTextModeOnStdout() {
|
||||
std::fflush(stdout);
|
||||
#if _WIN32
|
||||
_setmode(_fileno(stdout), _O_TEXT);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace shaderc_util
|
||||
139
3rdparty/shaderc/libshaderc_util/src/io_shaderc_test.cc
vendored
Normal file
139
3rdparty/shaderc/libshaderc_util/src/io_shaderc_test.cc
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
// Copyright 2015 The Shaderc Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "libshaderc_util/io_shaderc.h"
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
#include <fstream>
|
||||
|
||||
namespace {
|
||||
|
||||
using shaderc_util::GetBaseFileName;
|
||||
using shaderc_util::GetOutputStream;
|
||||
using shaderc_util::IsAbsolutePath;
|
||||
using shaderc_util::ReadFile;
|
||||
using shaderc_util::WriteFile;
|
||||
using testing::Eq;
|
||||
using testing::HasSubstr;
|
||||
|
||||
std::string ToString(const std::vector<char>& v) {
|
||||
return std::string(v.data(), v.size());
|
||||
}
|
||||
|
||||
class ReadFileTest : public testing::Test {
|
||||
protected:
|
||||
// A vector to pass to ReadFile.
|
||||
std::vector<char> read_data;
|
||||
};
|
||||
|
||||
TEST(IsAbsolutePathTest, Linux) {
|
||||
EXPECT_FALSE(IsAbsolutePath(""));
|
||||
EXPECT_TRUE(IsAbsolutePath("/"));
|
||||
EXPECT_FALSE(IsAbsolutePath("."));
|
||||
EXPECT_FALSE(IsAbsolutePath(".."));
|
||||
EXPECT_TRUE(IsAbsolutePath("/bin/echo"));
|
||||
EXPECT_TRUE(IsAbsolutePath("//etc/shadow"));
|
||||
EXPECT_TRUE(IsAbsolutePath("/../../../lib"));
|
||||
EXPECT_FALSE(IsAbsolutePath("./something"));
|
||||
EXPECT_FALSE(IsAbsolutePath("input"));
|
||||
EXPECT_FALSE(IsAbsolutePath("../test"));
|
||||
EXPECT_FALSE(IsAbsolutePath(" /abc"));
|
||||
EXPECT_TRUE(IsAbsolutePath("/abc def/ttt"));
|
||||
}
|
||||
|
||||
TEST(IsAbsolutePathTest, Windows) {
|
||||
EXPECT_TRUE(IsAbsolutePath(R"(\\Server1000\superuser\file)"));
|
||||
EXPECT_TRUE(IsAbsolutePath(R"(\\zzzz 1000\user with space\file with space)"));
|
||||
EXPECT_TRUE(
|
||||
IsAbsolutePath(R"(C:\Program Files (x86)\Windows Folder\shader.glsl)"));
|
||||
EXPECT_FALSE(IsAbsolutePath(R"(third_party\gmock)"));
|
||||
EXPECT_FALSE(IsAbsolutePath(R"(C:..\File.txt)"));
|
||||
}
|
||||
|
||||
TEST(GetBaseFileName, Linux) {
|
||||
EXPECT_EQ("", GetBaseFileName(""));
|
||||
EXPECT_EQ("", GetBaseFileName("/"));
|
||||
EXPECT_EQ("", GetBaseFileName("."));
|
||||
EXPECT_EQ("", GetBaseFileName(".."));
|
||||
EXPECT_EQ("echo", GetBaseFileName("/bin/echo"));
|
||||
EXPECT_EQ("shadow", GetBaseFileName("//etc/shadow"));
|
||||
EXPECT_EQ("lib", GetBaseFileName("/../../../lib"));
|
||||
EXPECT_EQ("something", GetBaseFileName("./something"));
|
||||
EXPECT_EQ("input", GetBaseFileName("input"));
|
||||
EXPECT_EQ("test", GetBaseFileName("../test"));
|
||||
EXPECT_EQ("abc", GetBaseFileName(" /abc"));
|
||||
EXPECT_EQ("ttt", GetBaseFileName("/abc def/ttt"));
|
||||
}
|
||||
|
||||
TEST(GetBaseFileName, Windows) {
|
||||
EXPECT_EQ("file", GetBaseFileName(R"(\\Server1000\superuser\file)"));
|
||||
EXPECT_EQ("file with space",
|
||||
GetBaseFileName(R"(\\zzzz 1000\user with space\file with space)"));
|
||||
EXPECT_EQ(
|
||||
"shader.glsl",
|
||||
GetBaseFileName(R"(C:\Program Files (x86)\Windows Folder\shader.glsl)"));
|
||||
EXPECT_EQ("gmock", GetBaseFileName(R"(third_party\gmock)"));
|
||||
EXPECT_EQ("File.txt", GetBaseFileName(R"(C:..\File.txt)"));
|
||||
}
|
||||
|
||||
TEST_F(ReadFileTest, CorrectContent) {
|
||||
ASSERT_TRUE(ReadFile("include_file.1", &read_data));
|
||||
EXPECT_EQ("The quick brown fox jumps over a lazy dog.", ToString(read_data));
|
||||
}
|
||||
|
||||
TEST_F(ReadFileTest, EmptyContent) {
|
||||
ASSERT_TRUE(ReadFile("dir/subdir/include_file.2", &read_data));
|
||||
EXPECT_TRUE(read_data.empty());
|
||||
}
|
||||
|
||||
TEST_F(ReadFileTest, FileNotFound) {
|
||||
EXPECT_FALSE(ReadFile("garbage garbage vjoiarhiupo hrfewi", &read_data));
|
||||
}
|
||||
|
||||
TEST_F(ReadFileTest, EmptyFilename) { EXPECT_FALSE(ReadFile("", &read_data)); }
|
||||
|
||||
TEST(WriteFiletest, BadStream) {
|
||||
std::ofstream fstream;
|
||||
std::ostringstream err;
|
||||
std::ostream* output_stream = GetOutputStream(
|
||||
"/this/should/not/be/writable/asdfasdfasdfasdf", &fstream, &err);
|
||||
EXPECT_EQ(nullptr, output_stream);
|
||||
EXPECT_TRUE(fstream.fail());
|
||||
EXPECT_EQ(nullptr, output_stream);
|
||||
EXPECT_THAT(err.str(), HasSubstr("cannot open output file"));
|
||||
}
|
||||
|
||||
TEST(WriteFileTest, Roundtrip) {
|
||||
const std::string content = "random content 12345";
|
||||
const std::string filename = "WriteFileTestOutput.tmp";
|
||||
std::ofstream fstream;
|
||||
std::ostringstream err;
|
||||
std::ostream* output_stream = GetOutputStream(filename, &fstream, &err);
|
||||
ASSERT_EQ(output_stream, &fstream);
|
||||
EXPECT_THAT(err.str(), Eq(""));
|
||||
ASSERT_TRUE(WriteFile(output_stream, content));
|
||||
std::vector<char> read_data;
|
||||
ASSERT_TRUE(ReadFile(filename, &read_data));
|
||||
EXPECT_EQ(content, ToString(read_data));
|
||||
}
|
||||
|
||||
TEST(OutputStreamTest, Stdout) {
|
||||
std::ofstream fstream;
|
||||
std::ostringstream err;
|
||||
std::ostream* output_stream = GetOutputStream("-", &fstream, &err);
|
||||
EXPECT_EQ(&std::cout, output_stream);
|
||||
EXPECT_THAT(err.str(), Eq(""));
|
||||
}
|
||||
} // anonymous namespace
|
||||
293
3rdparty/shaderc/libshaderc_util/src/message.cc
vendored
Normal file
293
3rdparty/shaderc/libshaderc_util/src/message.cc
vendored
Normal file
@@ -0,0 +1,293 @@
|
||||
// Copyright 2015 The Shaderc Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "libshaderc_util/message.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
|
||||
namespace shaderc_util {
|
||||
|
||||
namespace {
|
||||
|
||||
// Given a message, deduces and returns its type. If the message type is
|
||||
// recognized, advances *message past the prefix indicating the type. Otherwise,
|
||||
// leaves *message unchanged and returns MessageType::Unknown.
|
||||
MessageType DeduceMessageType(string_piece* message) {
|
||||
static const char kErrorMessage[] = "ERROR: ";
|
||||
static const char kWarningMessage[] = "WARNING: ";
|
||||
static const char kGlobalWarningMessage[] = "Warning, ";
|
||||
|
||||
if (message->starts_with(kErrorMessage)) {
|
||||
*message = message->substr(::strlen(kErrorMessage));
|
||||
return MessageType::Error;
|
||||
} else if (message->starts_with(kWarningMessage)) {
|
||||
*message = message->substr(::strlen(kWarningMessage));
|
||||
return MessageType::Warning;
|
||||
} else if (message->starts_with(kGlobalWarningMessage)) {
|
||||
*message = message->substr(::strlen(kGlobalWarningMessage));
|
||||
return MessageType::GlobalWarning;
|
||||
}
|
||||
return MessageType::Unknown;
|
||||
}
|
||||
|
||||
// Deduces a location specification from the given message. A location
|
||||
// specification is of the form "<source-name>:<line-number>:" and a trailing
|
||||
// space. If the deduction is successful, returns true and updates source_name
|
||||
// and line_number to the deduced source name and line numer respectively. The
|
||||
// prefix standing for the location specification in message is skipped.
|
||||
// Otherwise, returns false and keeps all parameters untouched.
|
||||
bool DeduceLocationSpec(string_piece* message, string_piece* source_name,
|
||||
string_piece* line_number) {
|
||||
if (!message || message->empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// When we find a pattern like this:
|
||||
// colon
|
||||
// digits
|
||||
// colon
|
||||
// space
|
||||
// Then deduce that the source_name is the text before the first colon,
|
||||
// the line number is the digits, and the message is the text after the
|
||||
// second colon.
|
||||
|
||||
const size_t size = message->size();
|
||||
if (size <= 4) {
|
||||
// A valid message must have a colon, a digit, a colon, and a space.
|
||||
return false;
|
||||
}
|
||||
// The last possible position of the first colon.
|
||||
const size_t first_colon_cutoff = size - 4;
|
||||
// The last possible position of the second colon.
|
||||
const size_t next_colon_cutoff = size - 2;
|
||||
|
||||
for (size_t first_colon_pos = message->find_first_of(':'), next_colon_pos = 0;
|
||||
|
||||
// There is a first colon, and it's not too close to the end
|
||||
(first_colon_pos != string_piece::npos) &&
|
||||
(first_colon_pos <= first_colon_cutoff);
|
||||
|
||||
// Try the next pair of colons.
|
||||
first_colon_pos = next_colon_pos) {
|
||||
// We're guaranteed to have at least 3 more characters.
|
||||
// Guarantee progress toward the end of the string.
|
||||
next_colon_pos = message->find_first_of(':', first_colon_pos + 1);
|
||||
if ((next_colon_pos == string_piece::npos) ||
|
||||
(next_colon_pos > next_colon_cutoff)) {
|
||||
// No valid solution.
|
||||
return false;
|
||||
}
|
||||
if (first_colon_pos + 1 == next_colon_pos) {
|
||||
// There is no room for digits.
|
||||
continue;
|
||||
}
|
||||
if ((message->data()[next_colon_pos + 1] != ' ')) {
|
||||
// There is no space character after the second colon.
|
||||
continue;
|
||||
}
|
||||
if (message->find_first_not_of("0123456789", first_colon_pos + 1) ==
|
||||
next_colon_pos) {
|
||||
// We found the first solution.
|
||||
*source_name = message->substr(0, first_colon_pos);
|
||||
*line_number = message->substr(first_colon_pos + 1,
|
||||
next_colon_pos - 1 - first_colon_pos);
|
||||
*message = message->substr(next_colon_pos + 2);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Returns true if the given message is a summary message.
|
||||
bool IsSummaryMessage(const string_piece& message) {
|
||||
const size_t space_loc = message.find_first_of(' ');
|
||||
if (space_loc == string_piece::npos) return false;
|
||||
const string_piece number = message.substr(0, space_loc);
|
||||
const string_piece rest = message.substr(space_loc + 1);
|
||||
if (!std::all_of(number.begin(), number.end(), ::isdigit)) return false;
|
||||
if (!rest.starts_with("compilation errors.")) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
MessageType ParseGlslangOutput(const string_piece& message,
|
||||
bool warnings_as_errors, bool suppress_warnings,
|
||||
string_piece* source_name,
|
||||
string_piece* line_number, string_piece* rest) {
|
||||
string_piece rest_of_message(message);
|
||||
source_name->clear();
|
||||
line_number->clear();
|
||||
rest->clear();
|
||||
|
||||
// The glslang warning/error messages are typically of the following form:
|
||||
// <message-type> <location-specification> <message-body>
|
||||
//
|
||||
// <message-type> can be "WARNING:", "ERROR:", or "Warning, ". "WARNING:"
|
||||
// means a warning message for a certain line, while "Warning, " means a
|
||||
// global one.
|
||||
//
|
||||
// <location-specification> is of the form:
|
||||
// <filename-or-string-number>:<line-number>:
|
||||
// It doesn't exist if the warning/error message is a global one.
|
||||
//
|
||||
// See Glslang's TInfoSink class implementation for details.
|
||||
|
||||
bool is_error = false;
|
||||
|
||||
// Handle <message-type>.
|
||||
switch (DeduceMessageType(&rest_of_message)) {
|
||||
case MessageType::Warning:
|
||||
if (suppress_warnings) return MessageType::Ignored;
|
||||
break;
|
||||
case MessageType::Error:
|
||||
is_error = true;
|
||||
break;
|
||||
case MessageType::GlobalWarning:
|
||||
if (suppress_warnings) return MessageType::Ignored;
|
||||
*rest = rest_of_message;
|
||||
return warnings_as_errors ? MessageType::GlobalError
|
||||
: MessageType::GlobalWarning;
|
||||
case MessageType::Unknown:
|
||||
*rest = rest_of_message;
|
||||
return MessageType::Unknown;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
rest_of_message = rest_of_message.strip_whitespace();
|
||||
if (rest_of_message.empty()) return MessageType::Unknown;
|
||||
|
||||
// Now we have stripped the <message-type>. Try to see if we can find
|
||||
// a <location-specification>.
|
||||
if (DeduceLocationSpec(&rest_of_message, source_name, line_number)) {
|
||||
*rest = rest_of_message;
|
||||
return (is_error || warnings_as_errors) ? MessageType::Error
|
||||
: MessageType::Warning;
|
||||
} else {
|
||||
// No <location-specification>. This is a global warning/error message.
|
||||
// A special kind of global message is summary message, which should
|
||||
// start with a number.
|
||||
*rest = rest_of_message;
|
||||
if (IsSummaryMessage(rest_of_message)) {
|
||||
return (is_error || warnings_as_errors) ? MessageType::ErrorSummary
|
||||
: MessageType::WarningSummary;
|
||||
}
|
||||
return (is_error || warnings_as_errors) ? MessageType::GlobalError
|
||||
: MessageType::GlobalWarning;
|
||||
}
|
||||
return MessageType::Unknown;
|
||||
}
|
||||
|
||||
bool PrintFilteredErrors(const string_piece& file_name,
|
||||
std::ostream* error_stream, bool warnings_as_errors,
|
||||
bool suppress_warnings, const char* error_list,
|
||||
size_t* total_warnings, size_t* total_errors) {
|
||||
const char* ignored_error_strings[] = {
|
||||
"Warning, version 310 is not yet complete; most version-specific "
|
||||
"features are present, but some are missing.",
|
||||
"Warning, version 400 is not yet complete; most version-specific "
|
||||
"features are present, but some are missing.",
|
||||
"Warning, version 410 is not yet complete; most version-specific "
|
||||
"features are present, but some are missing.",
|
||||
"Warning, version 420 is not yet complete; most version-specific "
|
||||
"features are present, but some are missing.",
|
||||
"Warning, version 430 is not yet complete; most version-specific "
|
||||
"features are present, but some are missing.",
|
||||
"Warning, version 440 is not yet complete; most version-specific "
|
||||
"features are present, but some are missing.",
|
||||
"Warning, version 450 is not yet complete; most version-specific "
|
||||
"features are present, but some are missing.",
|
||||
"Linked vertex stage:", "Linked fragment stage:",
|
||||
"Linked tessellation control stage:",
|
||||
"Linked tessellation evaluation stage:", "Linked geometry stage:",
|
||||
"Linked compute stage:", ""};
|
||||
size_t existing_total_errors = *total_errors;
|
||||
string_piece error_messages(error_list);
|
||||
for (const string_piece& message : error_messages.get_fields('\n')) {
|
||||
if (std::find(std::begin(ignored_error_strings),
|
||||
std::end(ignored_error_strings),
|
||||
message) == std::end(ignored_error_strings)) {
|
||||
string_piece source_name;
|
||||
string_piece line_number;
|
||||
string_piece rest;
|
||||
const MessageType type =
|
||||
ParseGlslangOutput(message, warnings_as_errors, suppress_warnings,
|
||||
&source_name, &line_number, &rest);
|
||||
string_piece name = file_name;
|
||||
if (!source_name.empty()) {
|
||||
// -1 is the string number for the preamble injected by us.
|
||||
name = source_name == "-1" ? "<command line>" : source_name;
|
||||
}
|
||||
switch (type) {
|
||||
case MessageType::Error:
|
||||
case MessageType::Warning:
|
||||
assert(!name.empty() && !line_number.empty() && !rest.empty());
|
||||
*error_stream << name << ":" << line_number << ": "
|
||||
<< (type == MessageType::Error ? "error: "
|
||||
: "warning: ")
|
||||
<< rest.strip_whitespace() << std::endl;
|
||||
*total_errors += type == MessageType::Error;
|
||||
*total_warnings += type == MessageType::Warning;
|
||||
break;
|
||||
case MessageType::ErrorSummary:
|
||||
case MessageType::WarningSummary:
|
||||
break;
|
||||
case MessageType::GlobalError:
|
||||
case MessageType::GlobalWarning:
|
||||
assert(!rest.empty());
|
||||
*total_errors += type == MessageType::GlobalError;
|
||||
*total_warnings += type == MessageType::GlobalWarning;
|
||||
*error_stream << name << ": "
|
||||
<< (type == MessageType::GlobalError ? "error"
|
||||
: "warning")
|
||||
<< ": " << rest.strip_whitespace() << std::endl;
|
||||
break;
|
||||
case MessageType::Unknown:
|
||||
*error_stream << name << ":";
|
||||
*error_stream << " " << message << std::endl;
|
||||
break;
|
||||
case MessageType::Ignored:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (existing_total_errors == *total_errors);
|
||||
}
|
||||
|
||||
// Outputs the number of warnings and errors if there are any.
|
||||
void OutputMessages(std::ostream* error_stream, size_t total_warnings,
|
||||
size_t total_errors) {
|
||||
if (total_warnings > 0 || total_errors > 0) {
|
||||
if (total_warnings > 0 && total_errors > 0) {
|
||||
*error_stream << total_warnings << " warning"
|
||||
<< (total_warnings > 1 ? "s" : "") << " and "
|
||||
<< total_errors << " error" << (total_errors > 1 ? "s" : "")
|
||||
<< " generated." << std::endl;
|
||||
} else if (total_warnings > 0) {
|
||||
*error_stream << total_warnings << " warning"
|
||||
<< (total_warnings > 1 ? "s" : "") << " generated."
|
||||
<< std::endl;
|
||||
} else if (total_errors > 0) {
|
||||
*error_stream << total_errors << " error" << (total_errors > 1 ? "s" : "")
|
||||
<< " generated." << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace glslc
|
||||
281
3rdparty/shaderc/libshaderc_util/src/message_test.cc
vendored
Normal file
281
3rdparty/shaderc/libshaderc_util/src/message_test.cc
vendored
Normal file
@@ -0,0 +1,281 @@
|
||||
// Copyright 2015 The Shaderc Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Some of the tests here check code paths that are not checked by
|
||||
// integration tests.
|
||||
// Generally, these would be conditions not generated by the Glslang
|
||||
// compiler. It's easier to write these unit tests than to inject
|
||||
// a dependency on a fake compiler.
|
||||
#include "libshaderc_util/message.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using shaderc_util::MessageType;
|
||||
using shaderc_util::ParseGlslangOutput;
|
||||
using shaderc_util::string_piece;
|
||||
|
||||
namespace {
|
||||
|
||||
TEST(ParseGlslangOutputTest, EmptyMessageBody) {
|
||||
string_piece segment_number;
|
||||
string_piece line_number;
|
||||
string_piece rest;
|
||||
EXPECT_EQ(MessageType::Unknown,
|
||||
ParseGlslangOutput("WARNING: ", false, false, &segment_number,
|
||||
&line_number, &rest));
|
||||
EXPECT_EQ(MessageType::Unknown,
|
||||
ParseGlslangOutput("ERROR: ", false, false, &segment_number,
|
||||
&line_number, &rest));
|
||||
}
|
||||
|
||||
TEST(ParseGlslangOutputTest, GlobalError) {
|
||||
string_piece segment_number;
|
||||
string_piece line_number;
|
||||
string_piece rest;
|
||||
EXPECT_EQ(
|
||||
MessageType::GlobalError,
|
||||
ParseGlslangOutput("ERROR: too many functions: got 1666473 of them",
|
||||
false, false, &segment_number, &line_number, &rest));
|
||||
EXPECT_EQ("too many functions: got 1666473 of them", rest.str());
|
||||
|
||||
EXPECT_EQ(
|
||||
MessageType::GlobalError,
|
||||
ParseGlslangOutput(
|
||||
"ERROR: #version: versions before 150 do not allow a profile token",
|
||||
false, false, &segment_number, &line_number, &rest));
|
||||
EXPECT_EQ("#version: versions before 150 do not allow a profile token",
|
||||
rest.str());
|
||||
}
|
||||
|
||||
TEST(ParseGlslangOutputTest, GlobalWarning) {
|
||||
string_piece segment_number;
|
||||
string_piece line_number;
|
||||
string_piece rest;
|
||||
EXPECT_EQ(MessageType::GlobalWarning,
|
||||
ParseGlslangOutput("Warning, version 1000 is unknown.", false,
|
||||
false, &segment_number, &line_number, &rest));
|
||||
EXPECT_EQ("version 1000 is unknown.", rest.str());
|
||||
}
|
||||
|
||||
TEST(ParseGlslangOutputTest, InvalidSuffixAfterSegmentNumber) {
|
||||
string_piece segment_number;
|
||||
string_piece line_number;
|
||||
string_piece rest;
|
||||
EXPECT_EQ(MessageType::GlobalWarning,
|
||||
ParseGlslangOutput("WARNING: 12a", false, false, &segment_number,
|
||||
&line_number, &rest));
|
||||
EXPECT_EQ(MessageType::GlobalError,
|
||||
ParseGlslangOutput("WARNING: 12a", true, false, &segment_number,
|
||||
&line_number, &rest));
|
||||
EXPECT_EQ(MessageType::GlobalError,
|
||||
ParseGlslangOutput("ERROR: 42!", false, false, &segment_number,
|
||||
&line_number, &rest));
|
||||
}
|
||||
|
||||
TEST(ParseGlslangOutputTest, OnlyANumber) {
|
||||
string_piece source_name;
|
||||
string_piece line_number;
|
||||
string_piece rest;
|
||||
EXPECT_EQ(MessageType::GlobalWarning,
|
||||
ParseGlslangOutput("WARNING: 12", false, false, &source_name,
|
||||
&line_number, &rest));
|
||||
EXPECT_TRUE(source_name.empty());
|
||||
EXPECT_TRUE(line_number.empty());
|
||||
EXPECT_EQ("12", rest.str());
|
||||
|
||||
EXPECT_EQ(MessageType::GlobalError,
|
||||
ParseGlslangOutput("WARNING: 12", true, false, &source_name,
|
||||
&line_number, &rest));
|
||||
EXPECT_TRUE(source_name.empty());
|
||||
EXPECT_TRUE(line_number.empty());
|
||||
EXPECT_EQ("12", rest.str());
|
||||
|
||||
EXPECT_EQ(MessageType::GlobalError,
|
||||
ParseGlslangOutput("ERROR: 42", false, false, &source_name,
|
||||
&line_number, &rest));
|
||||
EXPECT_TRUE(source_name.empty());
|
||||
EXPECT_TRUE(line_number.empty());
|
||||
EXPECT_EQ("42", rest.str());
|
||||
}
|
||||
|
||||
TEST(ParseGlslangOutputTest, InvalidSuffixAfterSegmentNumberColon) {
|
||||
string_piece segment_number;
|
||||
string_piece line_number;
|
||||
string_piece rest;
|
||||
EXPECT_EQ(MessageType::GlobalWarning,
|
||||
ParseGlslangOutput("WARNING: 12:0", false, false, &segment_number,
|
||||
&line_number, &rest));
|
||||
EXPECT_EQ(MessageType::GlobalError,
|
||||
ParseGlslangOutput("ERROR: 42:1234", false, false, &segment_number,
|
||||
&line_number, &rest));
|
||||
}
|
||||
|
||||
TEST(ParseGlslangOutputTest, CompletelyUnrecognized) {
|
||||
string_piece segment_number;
|
||||
string_piece line_number;
|
||||
string_piece rest;
|
||||
EXPECT_EQ(MessageType::Unknown,
|
||||
ParseGlslangOutput("hello world!", false, false, &segment_number,
|
||||
&line_number, &rest));
|
||||
}
|
||||
|
||||
TEST(ParseGlslangOutputTest, LocationSpecification) {
|
||||
string_piece segment_number;
|
||||
string_piece line_number;
|
||||
string_piece rest;
|
||||
|
||||
// Glslang reading from strings can give string segment numbers as
|
||||
// the filename part.
|
||||
EXPECT_EQ(
|
||||
MessageType::Error,
|
||||
ParseGlslangOutput("ERROR: 0:2: '#' : invalid directive: foo", false,
|
||||
false, &segment_number, &line_number, &rest));
|
||||
EXPECT_EQ("0", segment_number.str());
|
||||
EXPECT_EQ("2", line_number.str());
|
||||
EXPECT_EQ("'#' : invalid directive: foo", rest.str());
|
||||
|
||||
EXPECT_EQ(
|
||||
MessageType::Warning,
|
||||
ParseGlslangOutput("WARNING: 15:36: The following extension must be "
|
||||
"enabled to use this feature:",
|
||||
false, false, &segment_number, &line_number, &rest));
|
||||
EXPECT_EQ("15", segment_number.str());
|
||||
EXPECT_EQ("36", line_number.str());
|
||||
EXPECT_EQ("The following extension must be enabled to use this feature:",
|
||||
rest.str());
|
||||
}
|
||||
|
||||
TEST(ParseGlslangOutputTest, FileName_BaseAndExtension) {
|
||||
string_piece source_name;
|
||||
string_piece line_number;
|
||||
string_piece rest;
|
||||
|
||||
EXPECT_EQ(MessageType::Error,
|
||||
ParseGlslangOutput("ERROR: shader.vert:5: something wrong", false,
|
||||
false, &source_name, &line_number, &rest));
|
||||
EXPECT_EQ("shader.vert", source_name.str());
|
||||
EXPECT_EQ("5", line_number.str());
|
||||
EXPECT_EQ("something wrong", rest.str());
|
||||
}
|
||||
|
||||
TEST(ParseGlslangOutputTest, FileName_BaseOnly) {
|
||||
string_piece source_name;
|
||||
string_piece line_number;
|
||||
string_piece rest;
|
||||
|
||||
EXPECT_EQ(MessageType::Warning,
|
||||
ParseGlslangOutput("WARNING: file:42: something wrong", false,
|
||||
false, &source_name, &line_number, &rest));
|
||||
EXPECT_EQ("file", source_name.str());
|
||||
EXPECT_EQ("42", line_number.str());
|
||||
EXPECT_EQ("something wrong", rest.str());
|
||||
}
|
||||
|
||||
TEST(ParseGlslangOutputTest, FileName_HexNumber) {
|
||||
string_piece source_name;
|
||||
string_piece line_number;
|
||||
string_piece rest;
|
||||
|
||||
EXPECT_EQ(MessageType::Warning,
|
||||
ParseGlslangOutput("WARNING: 0xdeedbeef:0: wa:ha:ha", false, false,
|
||||
&source_name, &line_number, &rest));
|
||||
EXPECT_EQ("0xdeedbeef", source_name.str());
|
||||
EXPECT_EQ("0", line_number.str());
|
||||
EXPECT_EQ("wa:ha:ha", rest.str());
|
||||
}
|
||||
|
||||
TEST(ParseGlslangOutputTest, FileName_ContainsColons) {
|
||||
string_piece source_name;
|
||||
string_piece line_number;
|
||||
string_piece rest;
|
||||
|
||||
EXPECT_EQ(MessageType::Warning,
|
||||
ParseGlslangOutput("WARNING: foo:bar:0: wa:ha:ha", false, false,
|
||||
&source_name, &line_number, &rest));
|
||||
EXPECT_EQ("foo:bar", source_name.str());
|
||||
EXPECT_EQ("0", line_number.str());
|
||||
EXPECT_EQ("wa:ha:ha", rest.str());
|
||||
}
|
||||
|
||||
TEST(ParseGlslangOutputTest, NoFile) {
|
||||
string_piece source_name;
|
||||
string_piece line_number;
|
||||
string_piece rest;
|
||||
|
||||
EXPECT_EQ(MessageType::Warning,
|
||||
ParseGlslangOutput("WARNING: :12: abc", false, false, &source_name,
|
||||
&line_number, &rest));
|
||||
EXPECT_EQ("", source_name.str());
|
||||
EXPECT_EQ("12", line_number.str());
|
||||
EXPECT_EQ("abc", rest.str());
|
||||
}
|
||||
|
||||
TEST(ParseGlslangOutputTest, NoLineNumber_InferredAsGlobalNoLocation) {
|
||||
string_piece source_name;
|
||||
string_piece line_number;
|
||||
string_piece rest;
|
||||
|
||||
// No solution since there is no room for digits.
|
||||
EXPECT_EQ(MessageType::GlobalWarning,
|
||||
ParseGlslangOutput("WARNING: foo:: abc", false, false,
|
||||
&source_name, &line_number, &rest));
|
||||
EXPECT_EQ("", source_name.str());
|
||||
EXPECT_EQ("", line_number.str());
|
||||
EXPECT_EQ("foo:: abc", rest.str());
|
||||
}
|
||||
|
||||
TEST(ParseGlslangOutputTest, NoSpaceAfterColon_InferredAsGlobalNoLocation) {
|
||||
string_piece source_name;
|
||||
string_piece line_number;
|
||||
string_piece rest;
|
||||
|
||||
// No solution since there is no space after the line-number-and-colon.
|
||||
EXPECT_EQ(MessageType::GlobalWarning,
|
||||
ParseGlslangOutput("WARNING: foo:12:abc", false, false,
|
||||
&source_name, &line_number, &rest));
|
||||
EXPECT_EQ("", source_name.str());
|
||||
EXPECT_EQ("", line_number.str());
|
||||
EXPECT_EQ("foo:12:abc", rest.str());
|
||||
}
|
||||
|
||||
TEST(ParseGlslangOutputTest, WindowsPath) {
|
||||
string_piece source_name;
|
||||
string_piece line_number;
|
||||
string_piece rest;
|
||||
|
||||
EXPECT_EQ(
|
||||
MessageType::Error,
|
||||
ParseGlslangOutput(R"(ERROR: C:\path\to\shader.glsl:5: something wrong)",
|
||||
false, false, &source_name, &line_number, &rest));
|
||||
EXPECT_EQ(R"(C:\path\to\shader.glsl)", source_name.str());
|
||||
EXPECT_EQ("5", line_number.str());
|
||||
EXPECT_EQ("something wrong", rest.str());
|
||||
|
||||
EXPECT_EQ(
|
||||
MessageType::Warning,
|
||||
ParseGlslangOutput(R"(WARNING: \\path\without\drive.vert:42: BOOM!)",
|
||||
false, false, &source_name, &line_number, &rest));
|
||||
EXPECT_EQ(R"(\\path\without\drive.vert)", source_name.str());
|
||||
EXPECT_EQ("42", line_number.str());
|
||||
EXPECT_EQ("BOOM!", rest.str());
|
||||
|
||||
EXPECT_EQ(MessageType::Warning,
|
||||
ParseGlslangOutput(R"(WARNING: X:\123.456\789:0: wa:ha:ha)", false,
|
||||
false, &source_name, &line_number, &rest));
|
||||
EXPECT_EQ(R"(X:\123.456\789)", source_name.str());
|
||||
EXPECT_EQ("0", line_number.str());
|
||||
EXPECT_EQ("wa:ha:ha", rest.str());
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
51
3rdparty/shaderc/libshaderc_util/src/mutex_test.cc
vendored
Normal file
51
3rdparty/shaderc/libshaderc_util/src/mutex_test.cc
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
// Copyright 2015 The Shaderc Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "libshaderc_util/mutex.h"
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <thread>
|
||||
|
||||
namespace {
|
||||
|
||||
TEST(MutexTest, CanCreateMutex) {
|
||||
shaderc_util::mutex mutex;
|
||||
mutex.lock();
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
#ifndef SHADERC_DISABLE_THREADED_TESTS
|
||||
|
||||
void increment_by_1000(shaderc_util::mutex& mut, int& i) {
|
||||
for(size_t j = 0; j < 1000; ++j) {
|
||||
mut.lock();
|
||||
i = i + 1;
|
||||
mut.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MutexTest, MutexLocks) {
|
||||
shaderc_util::mutex mutex;
|
||||
int i = 0;
|
||||
std::thread t1([&mutex, &i]() { increment_by_1000(mutex, i); });
|
||||
std::thread t2([&mutex, &i]() { increment_by_1000(mutex, i); });
|
||||
std::thread t3([&mutex, &i]() { increment_by_1000(mutex, i); });
|
||||
t1.join();
|
||||
t2.join();
|
||||
t3.join();
|
||||
EXPECT_EQ(3000, i);
|
||||
}
|
||||
#endif // SHADERC_DISABLE_THREADED_TESTS
|
||||
|
||||
} // anonymous namespace
|
||||
153
3rdparty/shaderc/libshaderc_util/src/resources.cc
vendored
Normal file
153
3rdparty/shaderc/libshaderc_util/src/resources.cc
vendored
Normal file
@@ -0,0 +1,153 @@
|
||||
// Copyright 2015 The Shaderc Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "libshaderc_util/resources.h"
|
||||
|
||||
#include "glslang/Include/ResourceLimits.h"
|
||||
|
||||
namespace shaderc_util {
|
||||
|
||||
// These numbers come from the OpenGL 4.4 core profile specification Chapter 23
|
||||
// unless otherwise specified.
|
||||
const TBuiltInResource kDefaultTBuiltInResource = {
|
||||
/*.maxLights = */ 8, // From OpenGL 3.0 table 6.46.
|
||||
/*.maxClipPlanes = */ 6, // From OpenGL 3.0 table 6.46.
|
||||
/*.maxTextureUnits = */ 2, // From OpenGL 3.0 table 6.50.
|
||||
/*.maxTextureCoords = */ 8, // From OpenGL 3.0 table 6.50.
|
||||
/*.maxVertexAttribs = */ 16,
|
||||
/*.maxVertexUniformComponents = */ 4096,
|
||||
/*.maxVaryingFloats = */ 60, // From OpenGLES 3.1 table 6.44.
|
||||
/*.maxVertexTextureImageUnits = */ 16,
|
||||
/*.maxCombinedTextureImageUnits = */ 80,
|
||||
/*.maxTextureImageUnits = */ 16,
|
||||
/*.maxFragmentUniformComponents = */ 1024,
|
||||
|
||||
// glslang has 32 maxDrawBuffers.
|
||||
// Pixel phone Vulkan driver in Android N has 8
|
||||
// maxFragmentOutputAttachments.
|
||||
/*.maxDrawBuffers = */ 8,
|
||||
|
||||
/*.maxVertexUniformVectors = */ 256,
|
||||
/*.maxVaryingVectors = */ 15, // From OpenGLES 3.1 table 6.44.
|
||||
/*.maxFragmentUniformVectors = */ 256,
|
||||
/*.maxVertexOutputVectors = */ 16, // maxVertexOutputComponents / 4
|
||||
/*.maxFragmentInputVectors = */ 15, // maxFragmentInputComponents / 4
|
||||
/*.minProgramTexelOffset = */ -8,
|
||||
/*.maxProgramTexelOffset = */ 7,
|
||||
/*.maxClipDistances = */ 8,
|
||||
/*.maxComputeWorkGroupCountX = */ 65535,
|
||||
/*.maxComputeWorkGroupCountY = */ 65535,
|
||||
/*.maxComputeWorkGroupCountZ = */ 65535,
|
||||
/*.maxComputeWorkGroupSizeX = */ 1024,
|
||||
/*.maxComputeWorkGroupSizeX = */ 1024,
|
||||
/*.maxComputeWorkGroupSizeZ = */ 64,
|
||||
/*.maxComputeUniformComponents = */ 512,
|
||||
/*.maxComputeTextureImageUnits = */ 16,
|
||||
/*.maxComputeImageUniforms = */ 8,
|
||||
/*.maxComputeAtomicCounters = */ 8,
|
||||
/*.maxComputeAtomicCounterBuffers = */ 1, // From OpenGLES 3.1 Table 6.43
|
||||
/*.maxVaryingComponents = */ 60,
|
||||
/*.maxVertexOutputComponents = */ 64,
|
||||
/*.maxGeometryInputComponents = */ 64,
|
||||
/*.maxGeometryOutputComponents = */ 128,
|
||||
/*.maxFragmentInputComponents = */ 128,
|
||||
/*.maxImageUnits = */ 8, // This does not seem to be defined anywhere,
|
||||
// set to ImageUnits.
|
||||
/*.maxCombinedImageUnitsAndFragmentOutputs = */ 8,
|
||||
/*.maxCombinedShaderOutputResources = */ 8,
|
||||
/*.maxImageSamples = */ 0,
|
||||
/*.maxVertexImageUniforms = */ 0,
|
||||
/*.maxTessControlImageUniforms = */ 0,
|
||||
/*.maxTessEvaluationImageUniforms = */ 0,
|
||||
/*.maxGeometryImageUniforms = */ 0,
|
||||
/*.maxFragmentImageUniforms = */ 8,
|
||||
/*.maxCombinedImageUniforms = */ 8,
|
||||
/*.maxGeometryTextureImageUnits = */ 16,
|
||||
/*.maxGeometryOutputVertices = */ 256,
|
||||
/*.maxGeometryTotalOutputComponents = */ 1024,
|
||||
/*.maxGeometryUniformComponents = */ 512,
|
||||
/*.maxGeometryVaryingComponents = */ 60, // Does not seem to be defined
|
||||
// anywhere, set equal to
|
||||
// maxVaryingComponents.
|
||||
/*.maxTessControlInputComponents = */ 128,
|
||||
/*.maxTessControlOutputComponents = */ 128,
|
||||
/*.maxTessControlTextureImageUnits = */ 16,
|
||||
/*.maxTessControlUniformComponents = */ 1024,
|
||||
/*.maxTessControlTotalOutputComponents = */ 4096,
|
||||
/*.maxTessEvaluationInputComponents = */ 128,
|
||||
/*.maxTessEvaluationOutputComponents = */ 128,
|
||||
/*.maxTessEvaluationTextureImageUnits = */ 16,
|
||||
/*.maxTessEvaluationUniformComponents = */ 1024,
|
||||
/*.maxTessPatchComponents = */ 120,
|
||||
/*.maxPatchVertices = */ 32,
|
||||
/*.maxTessGenLevel = */ 64,
|
||||
/*.maxViewports = */ 16,
|
||||
/*.maxVertexAtomicCounters = */ 0,
|
||||
/*.maxTessControlAtomicCounters = */ 0,
|
||||
/*.maxTessEvaluationAtomicCounters = */ 0,
|
||||
/*.maxGeometryAtomicCounters = */ 0,
|
||||
/*.maxFragmentAtomicCounters = */ 8,
|
||||
/*.maxCombinedAtomicCounters = */ 8,
|
||||
/*.maxAtomicCounterBindings = */ 1,
|
||||
/*.maxVertexAtomicCounterBuffers = */ 0, // From OpenGLES 3.1 Table 6.41.
|
||||
|
||||
// ARB_shader_atomic_counters.
|
||||
/*.maxTessControlAtomicCounterBuffers = */ 0,
|
||||
/*.maxTessEvaluationAtomicCounterBuffers = */ 0,
|
||||
/*.maxGeometryAtomicCounterBuffers = */ 0,
|
||||
// /ARB_shader_atomic_counters.
|
||||
|
||||
/*.maxFragmentAtomicCounterBuffers = */ 0, // From OpenGLES 3.1 Table 6.43.
|
||||
/*.maxCombinedAtomicCounterBuffers = */ 1,
|
||||
/*.maxAtomicCounterBufferSize = */ 32,
|
||||
/*.maxTransformFeedbackBuffers = */ 4,
|
||||
/*.maxTransformFeedbackInterleavedComponents = */ 64,
|
||||
/*.maxCullDistances = */ 8, // ARB_cull_distance.
|
||||
/*.maxCombinedClipAndCullDistances = */ 8, // ARB_cull_distance.
|
||||
/*.maxSamples = */ 4,
|
||||
/* .maxMeshOutputVerticesNV = */ 256,
|
||||
/* .maxMeshOutputPrimitivesNV = */ 512,
|
||||
/* .maxMeshWorkGroupSizeX_NV = */ 32,
|
||||
/* .maxMeshWorkGroupSizeY_NV = */ 1,
|
||||
/* .maxMeshWorkGroupSizeZ_NV = */ 1,
|
||||
/* .maxTaskWorkGroupSizeX_NV = */ 32,
|
||||
/* .maxTaskWorkGroupSizeY_NV = */ 1,
|
||||
/* .maxTaskWorkGroupSizeZ_NV = */ 1,
|
||||
/* .maxMeshViewCountNV = */ 4,
|
||||
/* .maxMeshOutputVerticesEXT = */ 256,
|
||||
/* .maxMeshOutputPrimitivesEXT = */ 256,
|
||||
/* .maxMeshWorkGroupSizeX_EXT = */ 128,
|
||||
/* .maxMeshWorkGroupSizeY_EXT = */ 128,
|
||||
/* .maxMeshWorkGroupSizeZ_EXT = */ 128,
|
||||
/* .maxTaskWorkGroupSizeX_EXT = */ 128,
|
||||
/* .maxTaskWorkGroupSizeY_EXT = */ 128,
|
||||
/* .maxTaskWorkGroupSizeZ_EXT = */ 128,
|
||||
/* .maxMeshViewCountEXT = */ 4,
|
||||
/* .maxDualSourceDrawBuffersEXT = */ 1,
|
||||
// This is the glslang TLimits structure.
|
||||
// It defines whether or not the following features are enabled.
|
||||
// We want them to all be enabled.
|
||||
/*.limits = */ {
|
||||
/*.nonInductiveForLoops = */ 1,
|
||||
/*.whileLoops = */ 1,
|
||||
/*.doWhileLoops = */ 1,
|
||||
/*.generalUniformIndexing = */ 1,
|
||||
/*.generalAttributeMatrixVectorIndexing = */ 1,
|
||||
/*.generalVaryingIndexing = */ 1,
|
||||
/*.generalSamplerIndexing = */ 1,
|
||||
/*.generalVariableIndexing = */ 1,
|
||||
/*.generalConstantMatrixVectorIndexing = */ 1,
|
||||
}};
|
||||
|
||||
} // namespace shaderc_util
|
||||
53
3rdparty/shaderc/libshaderc_util/src/shader_stage.cc
vendored
Normal file
53
3rdparty/shaderc/libshaderc_util/src/shader_stage.cc
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
// Copyright 2015 The Shaderc Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "libshaderc_util/shader_stage.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// Maps an identifier to a language.
|
||||
struct LanguageMapping {
|
||||
const char* id;
|
||||
EShLanguage language;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace shaderc_util {
|
||||
|
||||
EShLanguage MapStageNameToLanguage(const string_piece& stage_name) {
|
||||
const LanguageMapping string_to_stage[] = {
|
||||
{"vertex", EShLangVertex},
|
||||
{"fragment", EShLangFragment},
|
||||
{"tesscontrol", EShLangTessControl},
|
||||
{"tesseval", EShLangTessEvaluation},
|
||||
{"geometry", EShLangGeometry},
|
||||
{"compute", EShLangCompute},
|
||||
{"raygen", EShLangRayGenNV},
|
||||
{"intersect", EShLangIntersectNV},
|
||||
{"anyhit", EShLangAnyHitNV},
|
||||
{"closest", EShLangClosestHitNV},
|
||||
{"miss", EShLangMissNV},
|
||||
{"callable", EShLangCallableNV},
|
||||
{"task", EShLangTaskNV},
|
||||
{"mesh", EShLangMeshNV},
|
||||
};
|
||||
|
||||
for (const auto& entry : string_to_stage) {
|
||||
if (stage_name == entry.id) return entry.language;
|
||||
}
|
||||
return EShLangCount;
|
||||
}
|
||||
|
||||
} // namespace shaderc_util
|
||||
172
3rdparty/shaderc/libshaderc_util/src/spirv_tools_wrapper.cc
vendored
Normal file
172
3rdparty/shaderc/libshaderc_util/src/spirv_tools_wrapper.cc
vendored
Normal file
@@ -0,0 +1,172 @@
|
||||
// Copyright 2016 The Shaderc Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "libshaderc_util/spirv_tools_wrapper.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
||||
#include "spirv-tools/libspirv.hpp"
|
||||
#include "spirv-tools/optimizer.hpp"
|
||||
|
||||
namespace shaderc_util {
|
||||
|
||||
namespace {
|
||||
|
||||
// Gets the corresponding target environment used in SPIRV-Tools.
|
||||
spv_target_env GetSpirvToolsTargetEnv(Compiler::TargetEnv env,
|
||||
Compiler::TargetEnvVersion version) {
|
||||
switch (env) {
|
||||
case Compiler::TargetEnv::Vulkan:
|
||||
switch (version) {
|
||||
case Compiler::TargetEnvVersion::Default:
|
||||
return SPV_ENV_VULKAN_1_0;
|
||||
case Compiler::TargetEnvVersion::Vulkan_1_0:
|
||||
return SPV_ENV_VULKAN_1_0;
|
||||
case Compiler::TargetEnvVersion::Vulkan_1_1:
|
||||
return SPV_ENV_VULKAN_1_1;
|
||||
case Compiler::TargetEnvVersion::Vulkan_1_2:
|
||||
return SPV_ENV_VULKAN_1_2;
|
||||
case Compiler::TargetEnvVersion::Vulkan_1_3:
|
||||
return SPV_ENV_VULKAN_1_3;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case Compiler::TargetEnv::OpenGL:
|
||||
return SPV_ENV_OPENGL_4_5;
|
||||
case Compiler::TargetEnv::OpenGLCompat:
|
||||
// Errors out before getting here. But the compiler wants us to handle
|
||||
// enum anyway.
|
||||
return SPV_ENV_OPENGL_4_5;
|
||||
}
|
||||
assert(false && "unexpected target environment or version");
|
||||
return SPV_ENV_VULKAN_1_0;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
bool SpirvToolsDisassemble(Compiler::TargetEnv env,
|
||||
Compiler::TargetEnvVersion version,
|
||||
const std::vector<uint32_t>& binary,
|
||||
std::string* text_or_error) {
|
||||
spvtools::SpirvTools tools(GetSpirvToolsTargetEnv(env, version));
|
||||
std::ostringstream oss;
|
||||
tools.SetMessageConsumer([&oss](spv_message_level_t, const char*,
|
||||
const spv_position_t& position,
|
||||
const char* message) {
|
||||
oss << position.index << ": " << message;
|
||||
});
|
||||
const bool success =
|
||||
tools.Disassemble(binary, text_or_error,
|
||||
SPV_BINARY_TO_TEXT_OPTION_INDENT |
|
||||
SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
|
||||
if (!success) {
|
||||
*text_or_error = oss.str();
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool SpirvToolsAssemble(Compiler::TargetEnv env,
|
||||
Compiler::TargetEnvVersion version,
|
||||
const string_piece assembly, spv_binary* binary,
|
||||
std::string* errors) {
|
||||
auto spvtools_context =
|
||||
spvContextCreate(GetSpirvToolsTargetEnv(env, version));
|
||||
spv_diagnostic spvtools_diagnostic = nullptr;
|
||||
|
||||
*binary = nullptr;
|
||||
errors->clear();
|
||||
|
||||
const bool success =
|
||||
spvTextToBinary(spvtools_context, assembly.data(), assembly.size(),
|
||||
binary, &spvtools_diagnostic) == SPV_SUCCESS;
|
||||
if (!success) {
|
||||
std::ostringstream oss;
|
||||
oss << spvtools_diagnostic->position.line + 1 << ":"
|
||||
<< spvtools_diagnostic->position.column + 1 << ": "
|
||||
<< spvtools_diagnostic->error;
|
||||
*errors = oss.str();
|
||||
}
|
||||
|
||||
spvDiagnosticDestroy(spvtools_diagnostic);
|
||||
spvContextDestroy(spvtools_context);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool SpirvToolsOptimize(Compiler::TargetEnv env,
|
||||
Compiler::TargetEnvVersion version,
|
||||
const std::vector<PassId>& enabled_passes,
|
||||
spvtools::OptimizerOptions& optimizer_options,
|
||||
std::vector<uint32_t>* binary, std::string* errors) {
|
||||
errors->clear();
|
||||
if (enabled_passes.empty()) return true;
|
||||
if (std::all_of(
|
||||
enabled_passes.cbegin(), enabled_passes.cend(),
|
||||
[](const PassId& pass) { return pass == PassId::kNullPass; })) {
|
||||
return true;
|
||||
}
|
||||
|
||||
spvtools::ValidatorOptions val_opts;
|
||||
// This allows flexible memory layout for HLSL.
|
||||
val_opts.SetSkipBlockLayout(true);
|
||||
// This allows HLSL legalization regarding resources.
|
||||
val_opts.SetRelaxLogicalPointer(true);
|
||||
// This uses relaxed rules for pre-legalized HLSL.
|
||||
val_opts.SetBeforeHlslLegalization(true);
|
||||
|
||||
// Set additional optimizer options.
|
||||
optimizer_options.set_validator_options(val_opts);
|
||||
optimizer_options.set_run_validator(true);
|
||||
|
||||
spvtools::Optimizer optimizer(GetSpirvToolsTargetEnv(env, version));
|
||||
|
||||
std::ostringstream oss;
|
||||
optimizer.SetMessageConsumer(
|
||||
[&oss](spv_message_level_t, const char*, const spv_position_t&,
|
||||
const char* message) { oss << message << "\n"; });
|
||||
|
||||
for (const auto& pass : enabled_passes) {
|
||||
switch (pass) {
|
||||
case PassId::kLegalizationPasses:
|
||||
optimizer.RegisterLegalizationPasses();
|
||||
break;
|
||||
case PassId::kPerformancePasses:
|
||||
optimizer.RegisterPerformancePasses();
|
||||
break;
|
||||
case PassId::kSizePasses:
|
||||
optimizer.RegisterSizePasses();
|
||||
break;
|
||||
case PassId::kNullPass:
|
||||
// We actually don't need to do anything for null pass.
|
||||
break;
|
||||
case PassId::kStripDebugInfo:
|
||||
optimizer.RegisterPass(spvtools::CreateStripDebugInfoPass());
|
||||
break;
|
||||
case PassId::kCompactIds:
|
||||
optimizer.RegisterPass(spvtools::CreateCompactIdsPass());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!optimizer.Run(binary->data(), binary->size(), binary,
|
||||
optimizer_options)) {
|
||||
*errors = oss.str();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace shaderc_util
|
||||
437
3rdparty/shaderc/libshaderc_util/src/string_piece_test.cc
vendored
Normal file
437
3rdparty/shaderc/libshaderc_util/src/string_piece_test.cc
vendored
Normal file
@@ -0,0 +1,437 @@
|
||||
// Copyright 2015 The Shaderc Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "libshaderc_util/string_piece.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <sstream>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "death_test.h"
|
||||
|
||||
namespace {
|
||||
|
||||
using shaderc_util::string_piece;
|
||||
|
||||
TEST(string_piece, creation) {
|
||||
std::string my_string("std::string");
|
||||
const char* my_c_string = "c::string";
|
||||
|
||||
string_piece my_string_piece(my_string);
|
||||
string_piece my_c_string_piece(my_c_string);
|
||||
string_piece my_partial_c_string_piece(my_c_string, my_c_string + 3);
|
||||
string_piece my_string_piece_string_piece(my_string_piece);
|
||||
|
||||
EXPECT_EQ("std::string", my_string_piece);
|
||||
EXPECT_EQ("c::string", my_c_string_piece);
|
||||
EXPECT_EQ("c::", my_partial_c_string_piece);
|
||||
EXPECT_EQ("std::string", my_string_piece_string_piece);
|
||||
}
|
||||
|
||||
TEST(string_piece, creation_with_empty_data) {
|
||||
string_piece my_string_piece(nullptr, nullptr);
|
||||
EXPECT_EQ("", my_string_piece);
|
||||
}
|
||||
|
||||
TEST(string_piece, creation_with_nullptr) {
|
||||
string_piece my_string_piece(nullptr);
|
||||
EXPECT_EQ("", my_string_piece);
|
||||
}
|
||||
|
||||
TEST(string_pieceDeathTest, creation_causing_assert) {
|
||||
EXPECT_DEBUG_DEATH_IF_SUPPORTED(string_piece("my_cstring", nullptr), ".*");
|
||||
EXPECT_DEBUG_DEATH_IF_SUPPORTED(string_piece(nullptr, "my_cstring"), ".*");
|
||||
}
|
||||
|
||||
TEST(string_pieceDeathTest, front) {
|
||||
EXPECT_DEBUG_DEATH_IF_SUPPORTED(string_piece(nullptr).front(), "Assertion");
|
||||
EXPECT_DEBUG_DEATH_IF_SUPPORTED(string_piece(nullptr, nullptr).front(),
|
||||
"Assertion");
|
||||
EXPECT_DEBUG_DEATH_IF_SUPPORTED(string_piece("").front(), "Assertion");
|
||||
string_piece s("nonempty");
|
||||
s.clear();
|
||||
EXPECT_DEBUG_DEATH_IF_SUPPORTED(s.front(), "Assertion");
|
||||
}
|
||||
|
||||
TEST(string_pieceDeathTest, back) {
|
||||
EXPECT_DEBUG_DEATH_IF_SUPPORTED(string_piece(nullptr).back(), "Assertion");
|
||||
EXPECT_DEBUG_DEATH_IF_SUPPORTED(string_piece(nullptr, nullptr).back(),
|
||||
"Assertion");
|
||||
EXPECT_DEBUG_DEATH_IF_SUPPORTED(string_piece("").back(), "Assertion");
|
||||
string_piece s("nonempty");
|
||||
s.clear();
|
||||
EXPECT_DEBUG_DEATH_IF_SUPPORTED(s.back(), "Assertion");
|
||||
}
|
||||
|
||||
TEST(string_piece, substr) {
|
||||
string_piece my_string("my really long string");
|
||||
EXPECT_EQ("my really long string", my_string.substr(0, string_piece::npos));
|
||||
EXPECT_EQ("my really long string", my_string.substr(0));
|
||||
EXPECT_EQ("really long string", my_string.substr(3, string_piece::npos));
|
||||
EXPECT_EQ("really long string", my_string.substr(3));
|
||||
EXPECT_EQ("really", my_string.substr(3, 6));
|
||||
}
|
||||
|
||||
TEST(string_piece, length) {
|
||||
EXPECT_EQ(0u, string_piece().size());
|
||||
EXPECT_TRUE(string_piece().empty());
|
||||
EXPECT_EQ(10u, string_piece("0123456789").size());
|
||||
|
||||
std::string my_string("std::string");
|
||||
EXPECT_EQ(my_string.size(), string_piece(my_string).size());
|
||||
}
|
||||
|
||||
TEST(string_piece, clear) {
|
||||
string_piece my_string("my really long string");
|
||||
EXPECT_EQ("my really long string", my_string);
|
||||
|
||||
string_piece other_string(my_string);
|
||||
EXPECT_EQ("my really long string", other_string);
|
||||
|
||||
my_string.clear();
|
||||
EXPECT_EQ("", my_string);
|
||||
EXPECT_EQ("my really long string", other_string);
|
||||
}
|
||||
|
||||
TEST(string_piece, str) {
|
||||
std::string test_string;
|
||||
{
|
||||
std::string temporary_string("my really long string");
|
||||
string_piece my_stringpiece(temporary_string);
|
||||
string_piece my_substring = my_stringpiece.substr(3, 6);
|
||||
|
||||
EXPECT_EQ("really", my_substring);
|
||||
test_string = my_substring.str();
|
||||
}
|
||||
EXPECT_EQ("really", test_string);
|
||||
}
|
||||
|
||||
template <char C>
|
||||
bool find_char(char c) {
|
||||
return c == C;
|
||||
}
|
||||
|
||||
TEST(string_piece, find_first_not_matching) {
|
||||
string_piece my_string("aaaaaaa b");
|
||||
EXPECT_EQ(7u, my_string.find_first_not_matching(find_char<'a'>));
|
||||
EXPECT_EQ(0u, my_string.find_first_not_matching(find_char<'b'>));
|
||||
EXPECT_EQ(0u, string_piece(" ").find_first_not_matching(::isdigit));
|
||||
size_t npos = string_piece::npos;
|
||||
EXPECT_EQ(npos, string_piece("").find_first_not_matching(::isdigit));
|
||||
EXPECT_EQ(npos, string_piece("123").find_first_not_matching(::isdigit));
|
||||
EXPECT_EQ(3u, string_piece("123 ").find_first_not_matching(::isdigit));
|
||||
}
|
||||
|
||||
TEST(string_piece, find_first_not_of) {
|
||||
size_t npos = string_piece::npos;
|
||||
string_piece my_string("aaaaaaa b");
|
||||
EXPECT_EQ(7u, my_string.find_first_not_of("a"));
|
||||
EXPECT_EQ(0u, my_string.find_first_not_of("b"));
|
||||
EXPECT_EQ(7u, my_string.find_first_not_of('a'));
|
||||
EXPECT_EQ(0u, my_string.find_first_not_of('b'));
|
||||
EXPECT_EQ(0u, string_piece(" ").find_first_not_of("0123456789"));
|
||||
|
||||
EXPECT_EQ(7u, my_string.find_first_not_of("a", 2));
|
||||
EXPECT_EQ(2u, my_string.find_first_not_of("b", 2));
|
||||
EXPECT_EQ(7u, my_string.find_first_not_of('a', 2));
|
||||
EXPECT_EQ(4u, my_string.find_first_not_of('b', 4));
|
||||
EXPECT_EQ(0u, string_piece(" ").find_first_not_of("0123456789"));
|
||||
EXPECT_EQ(npos, string_piece(" ").find_first_not_of("0123456789", 5));
|
||||
|
||||
EXPECT_EQ(npos, string_piece("").find_first_not_of("012345689"));
|
||||
EXPECT_EQ(npos, string_piece("").find_first_not_of("012345689", 1));
|
||||
EXPECT_EQ(npos, string_piece("123").find_first_not_of("0123456789"));
|
||||
EXPECT_EQ(npos, string_piece("123").find_first_not_of("0123456789", 1));
|
||||
EXPECT_EQ(3u, string_piece("123 ").find_first_not_of("0123456789", 2));
|
||||
EXPECT_EQ(npos, string_piece("123 ").find_first_not_of("0123456789", 4));
|
||||
EXPECT_EQ(npos, string_piece("").find_first_not_of("1"));
|
||||
EXPECT_EQ(npos, string_piece("111").find_first_not_of('1'));
|
||||
}
|
||||
|
||||
TEST(string_piece, find_first_of_char) {
|
||||
const size_t npos = string_piece::npos;
|
||||
string_piece my_string("my really long string");
|
||||
EXPECT_EQ(0u, my_string.find_first_of('m'));
|
||||
EXPECT_EQ(3u, my_string.find_first_of('r'));
|
||||
EXPECT_EQ(npos, my_string.find_first_of('z'));
|
||||
|
||||
size_t pos = my_string.find_first_of('l');
|
||||
EXPECT_EQ(6u, pos);
|
||||
// If pos points to a 'l' then we should just find that one
|
||||
EXPECT_EQ(6u, my_string.find_first_of('l', pos));
|
||||
EXPECT_EQ(7u, my_string.find_first_of('l', pos + 1));
|
||||
EXPECT_EQ(10u, my_string.find_first_of('l', pos + 2));
|
||||
EXPECT_EQ(npos, my_string.find_first_of('l', pos + 5));
|
||||
EXPECT_EQ(npos, my_string.find_first_of('z', 0));
|
||||
EXPECT_EQ(npos, my_string.find_first_of('z', npos));
|
||||
|
||||
my_string.clear();
|
||||
EXPECT_EQ(npos, my_string.find_first_of('a'));
|
||||
EXPECT_EQ(npos, my_string.find_first_of('a', 0));
|
||||
}
|
||||
|
||||
TEST(string_piece, find_first_of) {
|
||||
string_piece my_string("aaaaaa b");
|
||||
EXPECT_EQ(0u, my_string.find_first_of("a"));
|
||||
EXPECT_EQ(7u, my_string.find_first_of("b"));
|
||||
EXPECT_EQ(6u, my_string.find_first_of(" "));
|
||||
size_t npos = string_piece::npos;
|
||||
EXPECT_EQ(npos, my_string.find_first_of("xh"));
|
||||
EXPECT_EQ(6u, my_string.find_first_of(" x"));
|
||||
EXPECT_EQ(6u, my_string.find_first_of(" b"));
|
||||
EXPECT_EQ(0u, my_string.find_first_of("ab"));
|
||||
|
||||
EXPECT_EQ(6u, my_string.find_first_of(" x", 2));
|
||||
EXPECT_EQ(6u, my_string.find_first_of(" b", 2));
|
||||
EXPECT_EQ(2u, my_string.find_first_of("ab", 2));
|
||||
EXPECT_EQ(npos, my_string.find_first_of("ab", 10));
|
||||
|
||||
EXPECT_EQ(npos, my_string.find_first_of("c"));
|
||||
EXPECT_EQ(npos, my_string.find_first_of("c", 1));
|
||||
EXPECT_EQ(npos, string_piece(" ").find_first_of("a"));
|
||||
EXPECT_EQ(npos, string_piece(" ").find_first_of("a", 10));
|
||||
EXPECT_EQ(npos, string_piece("aa").find_first_of(""));
|
||||
EXPECT_EQ(npos, string_piece("aa").find_first_of("", 1));
|
||||
EXPECT_EQ(npos, string_piece("").find_first_of(""));
|
||||
EXPECT_EQ(npos, string_piece("").find_first_of("", 1));
|
||||
EXPECT_EQ(npos, string_piece("").find_first_of("a"));
|
||||
EXPECT_EQ(npos, string_piece("").find_first_of("ae"));
|
||||
EXPECT_EQ(npos, string_piece("").find_first_of("ae", 32));
|
||||
}
|
||||
|
||||
TEST(string_piece, find_last_of) {
|
||||
string_piece my_string("aaaaaa b");
|
||||
EXPECT_EQ(5u, my_string.find_last_of('a'));
|
||||
EXPECT_EQ(7u, my_string.find_last_of('b'));
|
||||
EXPECT_EQ(6u, my_string.find_last_of(' '));
|
||||
EXPECT_EQ(5u, my_string.find_last_of("a"));
|
||||
EXPECT_EQ(7u, my_string.find_last_of("b"));
|
||||
EXPECT_EQ(6u, my_string.find_last_of(" "));
|
||||
size_t npos = string_piece::npos;
|
||||
EXPECT_EQ(npos, my_string.find_last_of("xh"));
|
||||
EXPECT_EQ(6u, my_string.find_last_of(" x"));
|
||||
EXPECT_EQ(7u, my_string.find_last_of(" b"));
|
||||
EXPECT_EQ(7u, my_string.find_last_of("ab"));
|
||||
|
||||
EXPECT_EQ(4u, my_string.find_last_of('a', 4));
|
||||
EXPECT_EQ(5u, my_string.find_last_of('a', 6));
|
||||
EXPECT_EQ(0u, string_piece("abbbaa").find_last_of('a', 3));
|
||||
EXPECT_EQ(4u, string_piece("abbbaa").find_last_of('a', 4));
|
||||
EXPECT_EQ(5u, string_piece("abbbaa").find_last_of('a', 5));
|
||||
EXPECT_EQ(5u, string_piece("abbbaa").find_last_of('a', 6));
|
||||
EXPECT_EQ(npos, string_piece("abbbaa").find_last_of('c', 2));
|
||||
|
||||
EXPECT_EQ(npos, my_string.find_last_of("c"));
|
||||
EXPECT_EQ(npos, string_piece(" ").find_last_of("a"));
|
||||
EXPECT_EQ(npos, string_piece("aa").find_last_of(""));
|
||||
EXPECT_EQ(npos, string_piece("").find_last_of(""));
|
||||
EXPECT_EQ(npos, string_piece("").find_last_of("a"));
|
||||
EXPECT_EQ(npos, my_string.find_last_of('c'));
|
||||
EXPECT_EQ(npos, string_piece(" ").find_last_of('a'));
|
||||
EXPECT_EQ(npos, string_piece("").find_last_of('a'));
|
||||
EXPECT_EQ(npos, string_piece("").find_last_of("ae"));
|
||||
}
|
||||
|
||||
TEST(string_piece, begin_end) {
|
||||
const char* my_string = "my really long string";
|
||||
string_piece p(my_string);
|
||||
size_t pos = 0;
|
||||
for (auto it = p.begin(); it != p.end(); ++it) {
|
||||
EXPECT_EQ(my_string[pos++], *it);
|
||||
}
|
||||
pos = 0;
|
||||
for (auto c : p) {
|
||||
EXPECT_EQ(my_string[pos++], c);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(string_piece, front_back) {
|
||||
// EXPECT_TRUE() is used here because gtest will think we are comparing
|
||||
// between pointer and integer here if EXPECT_EQ() is used.
|
||||
const string_piece one_char("a");
|
||||
EXPECT_TRUE(one_char.front() == 'a');
|
||||
EXPECT_TRUE(one_char.back() == 'a');
|
||||
|
||||
const string_piece two_chars("bc");
|
||||
EXPECT_TRUE(two_chars.front() == 'b');
|
||||
EXPECT_TRUE(two_chars.back() == 'c');
|
||||
|
||||
const string_piece multi_chars("w vm g gg t\t");
|
||||
EXPECT_TRUE(multi_chars.front() == 'w');
|
||||
EXPECT_TRUE(multi_chars.back() == '\t');
|
||||
}
|
||||
|
||||
TEST(string_piece, starts_with) {
|
||||
EXPECT_TRUE(string_piece("my string").starts_with("my"));
|
||||
EXPECT_TRUE(string_piece("my string").starts_with("my s"));
|
||||
EXPECT_TRUE(string_piece("my string").starts_with("m"));
|
||||
EXPECT_TRUE(string_piece("my string").starts_with(""));
|
||||
EXPECT_TRUE(string_piece("my string").starts_with("my string"));
|
||||
EXPECT_TRUE(string_piece("").starts_with(""));
|
||||
|
||||
EXPECT_FALSE(string_piece("").starts_with("a"));
|
||||
EXPECT_FALSE(string_piece("my string").starts_with(" "));
|
||||
EXPECT_FALSE(string_piece("my string").starts_with("my stq"));
|
||||
EXPECT_FALSE(string_piece("my string").starts_with("a"));
|
||||
EXPECT_FALSE(string_piece("my string").starts_with("my strings"));
|
||||
}
|
||||
|
||||
TEST(string_piece, find) {
|
||||
const size_t npos = string_piece::npos;
|
||||
string_piece my_string("gooogle gooogle");
|
||||
|
||||
EXPECT_EQ(0u, my_string.find(""));
|
||||
|
||||
EXPECT_EQ(0u, my_string.find("g"));
|
||||
EXPECT_EQ(4u, my_string.find("g", 1));
|
||||
|
||||
EXPECT_EQ(0u, my_string.find("go"));
|
||||
EXPECT_EQ(8u, my_string.find("go", 1));
|
||||
|
||||
EXPECT_EQ(1u, my_string.find("oo"));
|
||||
EXPECT_EQ(1u, my_string.find("oo", 1));
|
||||
EXPECT_EQ(2u, my_string.find("oo", 2));
|
||||
EXPECT_EQ(9u, my_string.find("oo", 3));
|
||||
|
||||
EXPECT_EQ(4u, my_string.find("gle"));
|
||||
EXPECT_EQ(12u, my_string.find("gle", 5));
|
||||
|
||||
EXPECT_EQ(npos, my_string.find("0"));
|
||||
EXPECT_EQ(npos, my_string.find("does-not-exist"));
|
||||
EXPECT_EQ(npos, my_string.find("longer than gooogle gooogle"));
|
||||
|
||||
EXPECT_EQ(npos, my_string.find("", npos));
|
||||
EXPECT_EQ(npos, my_string.find("gle", npos));
|
||||
}
|
||||
|
||||
TEST(string_piece, get_fields) {
|
||||
string_piece input;
|
||||
std::vector<string_piece> expected_lines;
|
||||
EXPECT_EQ(expected_lines, input.get_fields('\n'));
|
||||
EXPECT_EQ(expected_lines, input.get_fields('\n', true));
|
||||
|
||||
input = "first line";
|
||||
expected_lines = {"first line"};
|
||||
EXPECT_EQ(expected_lines, input.get_fields('\n'));
|
||||
EXPECT_EQ(expected_lines, input.get_fields('\n', true));
|
||||
|
||||
input = "first line\n";
|
||||
expected_lines = {"first line"};
|
||||
EXPECT_EQ(expected_lines, input.get_fields('\n'));
|
||||
expected_lines = {"first line\n"};
|
||||
EXPECT_EQ(expected_lines, input.get_fields('\n', true));
|
||||
|
||||
input = "\nfirst line";
|
||||
expected_lines = {"", "first line"};
|
||||
EXPECT_EQ(expected_lines, input.get_fields('\n'));
|
||||
expected_lines = {"\n", "first line"};
|
||||
EXPECT_EQ(expected_lines, input.get_fields('\n', true));
|
||||
|
||||
input = "first line\nsecond line\nthird line\n";
|
||||
expected_lines = {"first line", "second line", "third line"};
|
||||
EXPECT_EQ(expected_lines, input.get_fields('\n'));
|
||||
expected_lines = {"first line\n", "second line\n", "third line\n"};
|
||||
EXPECT_EQ(expected_lines, input.get_fields('\n', true));
|
||||
|
||||
input = "first line\n\nsecond line\n\nthird line\n\n";
|
||||
expected_lines = {"first line", "", "second line", "", "third line", ""};
|
||||
EXPECT_EQ(expected_lines, input.get_fields('\n'));
|
||||
expected_lines = {"first line\n", "\n", "second line\n",
|
||||
"\n", "third line\n", "\n"};
|
||||
EXPECT_EQ(expected_lines, input.get_fields('\n', true));
|
||||
}
|
||||
|
||||
TEST(string_piece, operator_stream_out) {
|
||||
std::stringstream stream;
|
||||
string_piece my_string("my really long string");
|
||||
stream << my_string;
|
||||
EXPECT_EQ("my really long string", stream.str());
|
||||
stream.str("");
|
||||
stream << my_string.substr(3, 6);
|
||||
EXPECT_EQ("really", stream.str());
|
||||
stream.str("");
|
||||
stream << string_piece();
|
||||
EXPECT_EQ("", stream.str());
|
||||
}
|
||||
|
||||
TEST(string_piece, lrstrip) {
|
||||
string_piece nothing_to_remove("abcdefg");
|
||||
EXPECT_EQ("abcdefg", nothing_to_remove.lstrip("hijklmn"));
|
||||
EXPECT_EQ("abcdefg", nothing_to_remove.rstrip("hijklmn"));
|
||||
EXPECT_EQ("abcdefg", nothing_to_remove.strip("hijklmn"));
|
||||
|
||||
string_piece empty_string("");
|
||||
EXPECT_EQ(0u, empty_string.lstrip("google").size());
|
||||
EXPECT_EQ(0u, empty_string.rstrip("google").size());
|
||||
EXPECT_EQ(0u, empty_string.strip("google").size());
|
||||
|
||||
string_piece remove_nothing("asdfghjkl");
|
||||
EXPECT_EQ("asdfghjkl", remove_nothing.lstrip(""));
|
||||
EXPECT_EQ("asdfghjkl", remove_nothing.rstrip(""));
|
||||
EXPECT_EQ("asdfghjkl", remove_nothing.strip(""));
|
||||
|
||||
string_piece strip_numbers("0123g4o5o6g7l8e9");
|
||||
EXPECT_EQ("g4o5o6g7l8e9", strip_numbers.lstrip("0123456789"));
|
||||
EXPECT_EQ("0123g4o5o6g7l8e", strip_numbers.rstrip("0123456789"));
|
||||
EXPECT_EQ("g4o5o6g7l8e", strip_numbers.strip("0123456789"));
|
||||
}
|
||||
|
||||
TEST(string_piece, strip_whitespace) {
|
||||
string_piece lots_of_space(" b i n g o ");
|
||||
EXPECT_EQ("b i n g o", lots_of_space.strip_whitespace());
|
||||
|
||||
string_piece whitespaces("\v\t\f\n\rleft\r\t\f\n\vright\f\n\t\v\r");
|
||||
EXPECT_EQ("left\r\t\f\n\vright", whitespaces.strip_whitespace());
|
||||
|
||||
string_piece remove_all(" \t ");
|
||||
EXPECT_EQ(0u, remove_all.strip_whitespace().size());
|
||||
}
|
||||
|
||||
TEST(string_piece, not_equal) {
|
||||
EXPECT_FALSE(string_piece() != string_piece());
|
||||
EXPECT_FALSE(string_piece("") != string_piece());
|
||||
EXPECT_TRUE(string_piece() != string_piece(" "));
|
||||
EXPECT_FALSE(string_piece("abc") != string_piece("abc"));
|
||||
EXPECT_TRUE(string_piece("abc") != string_piece("abc "));
|
||||
EXPECT_TRUE(string_piece("abc") != string_piece("abd"));
|
||||
|
||||
EXPECT_FALSE("" != string_piece());
|
||||
EXPECT_FALSE("" != string_piece(""));
|
||||
EXPECT_TRUE(" " != string_piece(""));
|
||||
EXPECT_FALSE("abc" != string_piece("abc"));
|
||||
EXPECT_TRUE(" abc" != string_piece("abc"));
|
||||
EXPECT_TRUE("abd" != string_piece("abc"));
|
||||
}
|
||||
|
||||
TEST(string_piece, data) {
|
||||
EXPECT_EQ(nullptr, string_piece().data());
|
||||
const char* empty = "";
|
||||
EXPECT_EQ(empty, string_piece(empty).data());
|
||||
const char* space = " ";
|
||||
EXPECT_EQ(space, string_piece(space).data());
|
||||
const char* a = "a";
|
||||
EXPECT_EQ(a, string_piece(a).data());
|
||||
const char* abc = "abc";
|
||||
EXPECT_EQ(abc, string_piece(abc).data());
|
||||
EXPECT_EQ(abc + 1, string_piece(abc).substr(1).data());
|
||||
EXPECT_EQ(abc + 3, string_piece(abc).substr(3).data());
|
||||
}
|
||||
|
||||
TEST(string_piece, unordered_map) {
|
||||
std::unordered_map<string_piece, int> dict;
|
||||
dict["abc"] = 123;
|
||||
EXPECT_EQ(123, dict["abc"]);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
59
3rdparty/shaderc/libshaderc_util/src/version_profile.cc
vendored
Normal file
59
3rdparty/shaderc/libshaderc_util/src/version_profile.cc
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
// Copyright 2015 The Shaderc Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "libshaderc_util/version_profile.h"
|
||||
|
||||
#include <cctype>
|
||||
#include <sstream>
|
||||
|
||||
namespace {
|
||||
|
||||
const int kVersionNumberLength = 3;
|
||||
const int kMaxProfileLength = 13; // strlen(compatibility)
|
||||
const int kMaxVersionProfileLength = kVersionNumberLength + kMaxProfileLength;
|
||||
const int kMinVersionProfileLength = kVersionNumberLength;
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace shaderc_util {
|
||||
|
||||
bool ParseVersionProfile(const std::string& version_profile, int* version,
|
||||
EProfile* profile) {
|
||||
if (version_profile.size() < kMinVersionProfileLength ||
|
||||
version_profile.size() > kMaxVersionProfileLength ||
|
||||
!::isdigit(version_profile.front()))
|
||||
return false;
|
||||
|
||||
std::string profile_string;
|
||||
std::istringstream(version_profile) >> *version >> profile_string;
|
||||
|
||||
if (!IsKnownVersion(*version)) {
|
||||
return false;
|
||||
}
|
||||
if (profile_string.empty()) {
|
||||
*profile = ENoProfile;
|
||||
} else if (profile_string == "core") {
|
||||
*profile = ECoreProfile;
|
||||
} else if (profile_string == "es") {
|
||||
*profile = EEsProfile;
|
||||
} else if (profile_string == "compatibility") {
|
||||
*profile = ECompatibilityProfile;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace shaderc_util
|
||||
133
3rdparty/shaderc/libshaderc_util/src/version_profile_test.cc
vendored
Normal file
133
3rdparty/shaderc/libshaderc_util/src/version_profile_test.cc
vendored
Normal file
@@ -0,0 +1,133 @@
|
||||
// Copyright 2017 The Shaderc Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "libshaderc_util/version_profile.h"
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
|
||||
namespace {
|
||||
|
||||
using shaderc_util::IsKnownVersion;
|
||||
using shaderc_util::ParseVersionProfile;
|
||||
using ::testing::Eq;
|
||||
using ::testing::ValuesIn;
|
||||
|
||||
|
||||
TEST(IsKnownVersionTest, Samples) {
|
||||
EXPECT_TRUE(IsKnownVersion(100));
|
||||
EXPECT_TRUE(IsKnownVersion(110));
|
||||
EXPECT_TRUE(IsKnownVersion(120));
|
||||
EXPECT_TRUE(IsKnownVersion(130));
|
||||
EXPECT_TRUE(IsKnownVersion(140));
|
||||
EXPECT_TRUE(IsKnownVersion(150));
|
||||
EXPECT_TRUE(IsKnownVersion(300));
|
||||
EXPECT_TRUE(IsKnownVersion(330));
|
||||
EXPECT_TRUE(IsKnownVersion(310));
|
||||
EXPECT_TRUE(IsKnownVersion(400));
|
||||
EXPECT_TRUE(IsKnownVersion(410));
|
||||
EXPECT_TRUE(IsKnownVersion(420));
|
||||
EXPECT_TRUE(IsKnownVersion(430));
|
||||
EXPECT_TRUE(IsKnownVersion(440));
|
||||
EXPECT_TRUE(IsKnownVersion(450));
|
||||
EXPECT_TRUE(IsKnownVersion(460));
|
||||
EXPECT_FALSE(IsKnownVersion(101));
|
||||
EXPECT_FALSE(IsKnownVersion(470));
|
||||
}
|
||||
|
||||
|
||||
struct ParseVersionProfileCase {
|
||||
std::string input;
|
||||
bool success;
|
||||
// The following are only used when success is true.
|
||||
int expected_version;
|
||||
EProfile expected_profile;
|
||||
};
|
||||
|
||||
using ParseVersionProfileTest = ::testing::TestWithParam<ParseVersionProfileCase>;
|
||||
|
||||
TEST_P(ParseVersionProfileTest, Sample) {
|
||||
int version = 0;
|
||||
EProfile profile = EBadProfile;
|
||||
const bool result = ParseVersionProfile(GetParam().input, &version, &profile);
|
||||
EXPECT_THAT(result, GetParam().success);
|
||||
if (result) {
|
||||
EXPECT_THAT(version, GetParam().expected_version);
|
||||
EXPECT_THAT(profile, GetParam().expected_profile);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// For OpenGL ES GLSL (ESSL) versions, see
|
||||
// https://www.khronos.org/registry/OpenGL/index_e.php
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(OpenGLESCases, ParseVersionProfileTest,
|
||||
ValuesIn(std::vector<ParseVersionProfileCase>{
|
||||
{"100es", true, 100, EEsProfile},
|
||||
{"300es", true, 300, EEsProfile},
|
||||
{"310es", true, 310, EEsProfile},
|
||||
{"320es", true, 320, EEsProfile},
|
||||
{"99es", false, 0, EBadProfile},
|
||||
{"500es", false, 0, EBadProfile},
|
||||
}));
|
||||
|
||||
// For OpenGL GLSL versions, see
|
||||
// https://www.khronos.org/registry/OpenGL/index_gl.php
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(OpenGLBlankCases, ParseVersionProfileTest,
|
||||
ValuesIn(std::vector<ParseVersionProfileCase>{
|
||||
{"110", true, 110, ENoProfile},
|
||||
{"120", true, 120, ENoProfile},
|
||||
{"130", true, 130, ENoProfile},
|
||||
{"140", true, 140, ENoProfile},
|
||||
{"150", true, 150, ENoProfile},
|
||||
{"330", true, 330, ENoProfile},
|
||||
{"400", true, 400, ENoProfile},
|
||||
{"410", true, 410, ENoProfile},
|
||||
{"420", true, 420, ENoProfile},
|
||||
{"430", true, 430, ENoProfile},
|
||||
{"440", true, 440, ENoProfile},
|
||||
{"450", true, 450, ENoProfile},
|
||||
{"460", true, 460, ENoProfile},
|
||||
{"99", false, 0, EBadProfile},
|
||||
{"500", false, 0, EBadProfile},
|
||||
}));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(OpenGLCoreCases, ParseVersionProfileTest,
|
||||
ValuesIn(std::vector<ParseVersionProfileCase>{
|
||||
{"320core", true, 320, ECoreProfile},
|
||||
{"330core", true, 330, ECoreProfile},
|
||||
{"400core", true, 400, ECoreProfile},
|
||||
{"410core", true, 410, ECoreProfile},
|
||||
{"420core", true, 420, ECoreProfile},
|
||||
{"430core", true, 430, ECoreProfile},
|
||||
{"440core", true, 440, ECoreProfile},
|
||||
{"450core", true, 450, ECoreProfile},
|
||||
{"460core", true, 460, ECoreProfile},
|
||||
}));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
OpenGLCompatibilityCases, ParseVersionProfileTest,
|
||||
ValuesIn(std::vector<ParseVersionProfileCase>{
|
||||
{"320compatibility", true, 320, ECompatibilityProfile},
|
||||
{"330compatibility", true, 330, ECompatibilityProfile},
|
||||
{"400compatibility", true, 400, ECompatibilityProfile},
|
||||
{"410compatibility", true, 410, ECompatibilityProfile},
|
||||
{"420compatibility", true, 420, ECompatibilityProfile},
|
||||
{"430compatibility", true, 430, ECompatibilityProfile},
|
||||
{"440compatibility", true, 440, ECompatibilityProfile},
|
||||
{"450compatibility", true, 450, ECompatibilityProfile},
|
||||
{"460compatibility", true, 460, ECompatibilityProfile},
|
||||
}));
|
||||
|
||||
} // anonymous namespace
|
||||
16
3rdparty/shaderc/libshaderc_util/testdata/copy-to-build.cmake
vendored
Normal file
16
3rdparty/shaderc/libshaderc_util/testdata/copy-to-build.cmake
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
# Copyright 2020 The Shaderc Authors. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
file(GLOB all_files ${CMAKE_CURRENT_LIST_DIR}/*)
|
||||
file(COPY ${all_files} DESTINATION .)
|
||||
0
3rdparty/shaderc/libshaderc_util/testdata/dir/subdir/include_file.2
vendored
Normal file
0
3rdparty/shaderc/libshaderc_util/testdata/dir/subdir/include_file.2
vendored
Normal file
1
3rdparty/shaderc/libshaderc_util/testdata/include_file.1
vendored
Normal file
1
3rdparty/shaderc/libshaderc_util/testdata/include_file.1
vendored
Normal file
@@ -0,0 +1 @@
|
||||
The quick brown fox jumps over a lazy dog.
|
||||
Reference in New Issue
Block a user