GLSL writer: validate all entry points with glslang.

Generate and validate all entry points individually.
This is required since GLSL has separate shader files, and
can only have a single "main" entry point.

Bug: tint:1217
Change-Id: Ie5cb510aaef3b7c8a7573f5fa9446815284afecb
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/61920
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Stephen White <senorblanco@chromium.org>
Reviewed-by: Ben Clayton <bclayton@google.com>
This commit is contained in:
Stephen White 2021-10-14 14:39:36 +00:00 committed by Tint LUCI CQ
parent f3f2d0a218
commit 7cf3b28a87
11 changed files with 123 additions and 16 deletions

1
.gitignore vendored
View File

@ -16,6 +16,7 @@ out
testing testing
third_party/cpplint third_party/cpplint
third_party/binutils third_party/binutils
third_party/glslang
third_party/googletest third_party/googletest
third_party/gpuweb-cts third_party/gpuweb-cts
third_party/llvm-build third_party/llvm-build

4
DEPS
View File

@ -9,6 +9,7 @@ vars = {
'build_revision': 'c6c4a4c3ae890f2c020a087c90fb8c0b8be2816a', 'build_revision': 'c6c4a4c3ae890f2c020a087c90fb8c0b8be2816a',
'buildtools_revision': 'e3db55b4639f2a331af6f3708ca1fbd22322aac3', 'buildtools_revision': 'e3db55b4639f2a331af6f3708ca1fbd22322aac3',
'clang_revision': 'eb5ab41f3801e2085208204fd71a490573d72dfd', 'clang_revision': 'eb5ab41f3801e2085208204fd71a490573d72dfd',
'glslang_revision': '4b7b86d568b40f4b076259dc2fc4cdd006340f34',
'googletest_revision': '5c8ca58edfb304b2dd5e6061f83387470826dd87', 'googletest_revision': '5c8ca58edfb304b2dd5e6061f83387470826dd87',
'gpuweb_cts_revision': 'b0291fd966b55a5efc496772555b94842bde1085', 'gpuweb_cts_revision': 'b0291fd966b55a5efc496772555b94842bde1085',
'protobuf_revision': 'fde7cf7358ec7cd69e8db9be4f1fa6a5c431386a', 'protobuf_revision': 'fde7cf7358ec7cd69e8db9be4f1fa6a5c431386a',
@ -27,6 +28,9 @@ deps = {
'third_party/spirv-tools': Var('chromium_git') + Var('github') + 'third_party/spirv-tools': Var('chromium_git') + Var('github') +
'/KhronosGroup//SPIRV-Tools.git@' + Var('spirv_tools_revision'), '/KhronosGroup//SPIRV-Tools.git@' + Var('spirv_tools_revision'),
'third_party/glslang': Var('chromium_git') + Var('github') +
'/KhronosGroup/glslang.git@' + Var('glslang_revision'),
# Dependencies required to use GN/Clang in standalone # Dependencies required to use GN/Clang in standalone
'build': Var('chromium_git') + '/chromium/src/build@' + 'build': Var('chromium_git') + '/chromium/src/build@' +
Var('build_revision'), Var('build_revision'),

View File

@ -0,0 +1,15 @@
# Copyright 2021 The Dawn Authors
#
# 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.
glslang_spirv_tools_dir = "//third_party/spirv-tools"

View File

@ -25,6 +25,13 @@ executable("tint") {
"${tint_spirv_tools_dir}/:spvtools_val", "${tint_spirv_tools_dir}/:spvtools_val",
] ]
if (tint_build_glsl_writer) {
deps += [
"${tint_root_dir}/third_party/glslang:glslang_default_resource_limits_sources",
"${tint_root_dir}/third_party/glslang:glslang_lib_sources",
]
}
configs += [ configs += [
"${tint_root_dir}/src:tint_common_config", "${tint_root_dir}/src:tint_common_config",
"${tint_root_dir}/src:tint_config", "${tint_root_dir}/src:tint_config",

View File

@ -25,4 +25,15 @@ if(${TINT_BUILD_SPV_READER} OR ${TINT_BUILD_SPV_WRITER})
target_link_libraries(tint SPIRV-Tools) target_link_libraries(tint SPIRV-Tools)
endif() endif()
if(${TINT_BUILD_GLSL_WRITER})
target_link_libraries(tint glslang)
target_link_libraries(tint glslang-default-resource-limits)
if(NOT MSVC)
target_compile_options(tint PRIVATE
-Wno-reserved-id-macro
-Wno-shadow-field-in-constructor
-Wno-shadow
-Wno-weak-vtables
)
endif()
endif()

View File

@ -20,6 +20,11 @@
#include <string> #include <string>
#include <vector> #include <vector>
#if TINT_BUILD_GLSL_WRITER
#include "StandAlone/ResourceLimits.h"
#include "glslang/Public/ShaderLang.h"
#endif
#if TINT_BUILD_SPV_READER #if TINT_BUILD_SPV_READER
#include "spirv-tools/libspirv.hpp" #include "spirv-tools/libspirv.hpp"
#endif // TINT_BUILD_SPV_READER #endif // TINT_BUILD_SPV_READER
@ -845,25 +850,65 @@ bool GenerateHlsl(const tint::Program* program, const Options& options) {
#endif // TINT_BUILD_HLSL_WRITER #endif // TINT_BUILD_HLSL_WRITER
} }
#if TINT_BUILD_GLSL_WRITER
EShLanguage pipeline_stage_to_esh_language(tint::ast::PipelineStage stage) {
switch (stage) {
case tint::ast::PipelineStage::kFragment:
return EShLangFragment;
case tint::ast::PipelineStage::kVertex:
return EShLangVertex;
case tint::ast::PipelineStage::kCompute:
return EShLangCompute;
default:
TINT_ASSERT(AST, false);
return EShLangVertex;
}
}
#endif
/// Generate GLSL code for a program. /// Generate GLSL code for a program.
/// @param program the program to generate /// @param program the program to generate
/// @param options the options that Tint was invoked with /// @param options the options that Tint was invoked with
/// @returns true on success /// @returns true on success
bool GenerateGlsl(const tint::Program* program, const Options& options) { bool GenerateGlsl(const tint::Program* program, const Options& options) {
#if TINT_BUILD_GLSL_WRITER #if TINT_BUILD_GLSL_WRITER
if (options.validate) {
glslang::InitializeProcess();
}
tint::writer::glsl::Options gen_options; tint::writer::glsl::Options gen_options;
auto result = tint::writer::glsl::Generate(program, gen_options); tint::inspector::Inspector inspector(program);
if (!result.success) { for (auto& entry_point : inspector.GetEntryPoints()) {
PrintWGSL(std::cerr, *program); auto result =
std::cerr << "Failed to generate: " << result.error << std::endl; tint::writer::glsl::Generate(program, gen_options, entry_point.name);
return false; if (!result.success) {
} PrintWGSL(std::cerr, *program);
std::cerr << "Failed to generate: " << result.error << std::endl;
return false;
}
if (!WriteFile(options.output_file, "w", result.glsl)) { if (!WriteFile(options.output_file, "w", result.glsl)) {
return false; return false;
} }
// TODO(senorblanco): implement GLSL validation if (options.validate) {
for (auto entry_pt : result.entry_points) {
EShLanguage lang = pipeline_stage_to_esh_language(entry_pt.second);
glslang::TShader shader(lang);
const char* strings[1] = {result.glsl.c_str()};
int lengths[1] = {static_cast<int>(result.glsl.length())};
shader.setStringsWithLengths(strings, lengths, 1);
shader.setEntryPoint("main");
bool glslang_result =
shader.parse(&glslang::DefaultTBuiltInResource, 310, EEsProfile,
false, false, EShMsgDefault);
if (!glslang_result) {
std::cerr << "Error parsing GLSL shader:\n"
<< shader.getInfoLog() << "\n"
<< shader.getInfoDebugLog() << "\n";
}
}
}
}
return true; return true;
#else #else

View File

@ -28,6 +28,7 @@
#include "src/transform/pad_array_elements.h" #include "src/transform/pad_array_elements.h"
#include "src/transform/promote_initializers_to_const_var.h" #include "src/transform/promote_initializers_to_const_var.h"
#include "src/transform/simplify.h" #include "src/transform/simplify.h"
#include "src/transform/single_entry_point.h"
#include "src/transform/zero_init_workgroup_memory.h" #include "src/transform/zero_init_workgroup_memory.h"
TINT_INSTANTIATE_TYPEINFO(tint::transform::Glsl); TINT_INSTANTIATE_TYPEINFO(tint::transform::Glsl);
@ -69,6 +70,10 @@ Output Glsl::Run(const Program* in, const DataMap& inputs) {
// variables directly. // variables directly.
data.Add<CanonicalizeEntryPointIO::Config>( data.Add<CanonicalizeEntryPointIO::Config>(
CanonicalizeEntryPointIO::ShaderStyle::kHlsl); CanonicalizeEntryPointIO::ShaderStyle::kHlsl);
if (cfg) {
manager.Add<SingleEntryPoint>();
data.Add<SingleEntryPoint::Config>(cfg->entry_point);
}
auto out = manager.Run(in, data); auto out = manager.Run(in, data);
if (!out.program.IsValid()) { if (!out.program.IsValid()) {
return out; return out;
@ -94,7 +99,8 @@ void Glsl::AddEmptyEntryPoint(CloneContext& ctx) const {
ctx.dst->WorkgroupSize(1)}); ctx.dst->WorkgroupSize(1)});
} }
Glsl::Config::Config(bool disable_wi) : disable_workgroup_init(disable_wi) {} Glsl::Config::Config(const std::string& ep, bool disable_wi)
: entry_point(ep), disable_workgroup_init(disable_wi) {}
Glsl::Config::Config(const Config&) = default; Glsl::Config::Config(const Config&) = default;
Glsl::Config::~Config() = default; Glsl::Config::~Config() = default;

View File

@ -15,6 +15,8 @@
#ifndef SRC_TRANSFORM_GLSL_H_ #ifndef SRC_TRANSFORM_GLSL_H_
#define SRC_TRANSFORM_GLSL_H_ #define SRC_TRANSFORM_GLSL_H_
#include <string>
#include "src/transform/transform.h" #include "src/transform/transform.h"
namespace tint { namespace tint {
@ -32,9 +34,11 @@ class Glsl : public Castable<Glsl, Transform> {
/// Configuration options for the Glsl sanitizer transform. /// Configuration options for the Glsl sanitizer transform.
struct Config : public Castable<Data, transform::Data> { struct Config : public Castable<Data, transform::Data> {
/// Constructor /// Constructor
/// @param entry_point the root entry point function to generate
/// @param disable_workgroup_init `true` to disable workgroup memory zero /// @param disable_workgroup_init `true` to disable workgroup memory zero
/// initialization /// initialization
explicit Config(bool disable_workgroup_init = false); explicit Config(const std::string& entry_point,
bool disable_workgroup_init = false);
/// Copy constructor /// Copy constructor
Config(const Config&); Config(const Config&);
@ -42,6 +46,9 @@ class Glsl : public Castable<Glsl, Transform> {
/// Destructor /// Destructor
~Config() override; ~Config() override;
/// GLSL generator wraps a single entry point in a main() function.
std::string entry_point;
/// Set to `true` to disable workgroup memory zero initialization /// Set to `true` to disable workgroup memory zero initialization
bool disable_workgroup_init = false; bool disable_workgroup_init = false;
}; };

View File

@ -25,12 +25,16 @@ Result::Result() = default;
Result::~Result() = default; Result::~Result() = default;
Result::Result(const Result&) = default; Result::Result(const Result&) = default;
Result Generate(const Program* program, const Options&) { Result Generate(const Program* program,
const Options&,
const std::string& entry_point) {
Result result; Result result;
// Run the GLSL sanitizer. // Run the GLSL sanitizer.
transform::DataMap data;
data.Add<transform::Glsl::Config>(entry_point);
transform::Glsl sanitizer; transform::Glsl sanitizer;
auto output = sanitizer.Run(program); auto output = sanitizer.Run(program, data);
if (!output.program.IsValid()) { if (!output.program.IsValid()) {
result.success = false; result.success = false;
result.error = output.program.Diagnostics().str(); result.error = output.program.Diagnostics().str();

View File

@ -67,7 +67,9 @@ struct Result {
/// @param program the program to translate to GLSL /// @param program the program to translate to GLSL
/// @param options the configuration options to use when generating GLSL /// @param options the configuration options to use when generating GLSL
/// @returns the resulting GLSL and supplementary information /// @returns the resulting GLSL and supplementary information
Result Generate(const Program* program, const Options& options); Result Generate(const Program* program,
const Options& options,
const std::string& entry_point);
} // namespace glsl } // namespace glsl
} // namespace writer } // namespace writer

View File

@ -39,3 +39,8 @@ if(${TINT_BUILD_SPV_READER} OR ${TINT_BUILD_SPV_WRITER})
add_subdirectory("${TINT_THIRD_PARTY_DIR}/spirv-tools" "${CMAKE_BINARY_DIR}/third_party/spirv-tools" EXCLUDE_FROM_ALL) add_subdirectory("${TINT_THIRD_PARTY_DIR}/spirv-tools" "${CMAKE_BINARY_DIR}/third_party/spirv-tools" EXCLUDE_FROM_ALL)
endif() endif()
endif() endif()
if(${TINT_BUILD_GLSL_WRITER})
set(SPIRV-Headers_SOURCE_DIR "${TINT_THIRD_PARTY_DIR}/glslang")
add_subdirectory("${TINT_THIRD_PARTY_DIR}/glslang" "${CMAKE_BINARY_DIR}/third_party/glslang" EXCLUDE_FROM_ALL)
endif()