Add a `tint_info` command.
This CL adds a second command `tint_info`. The `tint_info` command can be used to dump information about a WGSL program to the console. This includes things like the inputs and outputs to an entrypoint along with structure information like offsets and alignments. Bug: 1825 Change-Id: Ia2fb4be08b39c1a592f78a388d34edf9af8b6a0e Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/118643 Commit-Queue: Dan Sinclair <dsinclair@chromium.org> Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: Ben Clayton <bclayton@google.com>
This commit is contained in:
parent
c1a181c947
commit
c1799cc75a
|
@ -66,6 +66,8 @@ add_library(tint_diagnostic_utils
|
|||
diagnostic/formatter.h
|
||||
diagnostic/printer.cc
|
||||
diagnostic/printer.h
|
||||
text/unicode.cc
|
||||
text/unicode.h
|
||||
utils/debugger.cc
|
||||
utils/debugger.h
|
||||
)
|
||||
|
@ -374,8 +376,6 @@ list(APPEND TINT_LIB_SRCS
|
|||
symbol.cc
|
||||
symbol.h
|
||||
tint.cc
|
||||
text/unicode.cc
|
||||
text/unicode.h
|
||||
traits.h
|
||||
transform/add_empty_entry_point.cc
|
||||
transform/add_empty_entry_point.h
|
||||
|
|
|
@ -15,9 +15,19 @@
|
|||
import("//build_overrides/build.gni")
|
||||
import("../../../tint_overrides_with_defaults.gni")
|
||||
|
||||
source_set("tint_cmd_helper") {
|
||||
sources = [
|
||||
"helper.cc",
|
||||
"helper.h",
|
||||
]
|
||||
|
||||
deps = [ "${tint_root_dir}/src/tint:libtint" ]
|
||||
}
|
||||
|
||||
executable("tint") {
|
||||
sources = [ "main.cc" ]
|
||||
deps = [
|
||||
":tint_cmd_helper",
|
||||
"${tint_root_dir}/src/tint:libtint",
|
||||
"${tint_root_dir}/src/tint:libtint_base_src",
|
||||
"${tint_root_dir}/src/tint:tint_utils_io",
|
||||
|
@ -44,3 +54,27 @@ executable("tint") {
|
|||
configs += [ "//build/config/compiler:no_chromium_code" ]
|
||||
}
|
||||
}
|
||||
|
||||
executable("tint_info") {
|
||||
sources = [ "info.cc" ]
|
||||
deps = [
|
||||
":tint_cmd_helper",
|
||||
"${tint_root_dir}/src/tint:libtint",
|
||||
"${tint_root_dir}/src/tint:libtint_base_src",
|
||||
"${tint_root_dir}/src/tint:tint_utils_io",
|
||||
"${tint_root_dir}/src/tint:tint_val",
|
||||
"${tint_spirv_tools_dir}/:spvtools",
|
||||
"${tint_spirv_tools_dir}/:spvtools_opt",
|
||||
"${tint_spirv_tools_dir}/:spvtools_val",
|
||||
]
|
||||
|
||||
configs += [
|
||||
"${tint_root_dir}/src/tint:tint_common_config",
|
||||
"${tint_root_dir}/src/tint:tint_config",
|
||||
]
|
||||
|
||||
if (build_with_chromium) {
|
||||
configs -= [ "//build/config/compiler:chromium_code" ]
|
||||
configs += [ "//build/config/compiler:no_chromium_code" ]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,23 +12,24 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
set(TINT_SRCS
|
||||
main.cc
|
||||
)
|
||||
|
||||
## Tint executable
|
||||
add_executable(tint ${TINT_SRCS})
|
||||
add_executable(tint "")
|
||||
target_sources(tint PRIVATE
|
||||
"helper.cc"
|
||||
"helper.h"
|
||||
"main.cc"
|
||||
)
|
||||
tint_default_compile_options(tint)
|
||||
target_link_libraries(tint libtint tint_val)
|
||||
|
||||
if(${TINT_BUILD_SPV_READER} OR ${TINT_BUILD_SPV_WRITER})
|
||||
if (${TINT_BUILD_SPV_READER} OR ${TINT_BUILD_SPV_WRITER})
|
||||
target_link_libraries(tint SPIRV-Tools)
|
||||
endif()
|
||||
|
||||
if(${TINT_BUILD_GLSL_WRITER})
|
||||
if (${TINT_BUILD_GLSL_WRITER})
|
||||
target_link_libraries(tint glslang)
|
||||
target_link_libraries(tint glslang-default-resource-limits)
|
||||
if(NOT MSVC)
|
||||
if (NOT MSVC)
|
||||
target_compile_options(tint PRIVATE
|
||||
-Wno-reserved-id-macro
|
||||
-Wno-shadow-field-in-constructor
|
||||
|
@ -37,3 +38,16 @@ if(${TINT_BUILD_GLSL_WRITER})
|
|||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_executable(tint_info "")
|
||||
target_sources(tint_info PRIVATE
|
||||
"helper.cc"
|
||||
"helper.h"
|
||||
"info.cc"
|
||||
)
|
||||
tint_default_compile_options(tint_info)
|
||||
target_link_libraries(tint_info libtint tint_val)
|
||||
|
||||
if (${TINT_BUILD_SPV_READER})
|
||||
target_link_libraries(tint_info SPIRV-Tools)
|
||||
endif()
|
||||
|
|
|
@ -0,0 +1,435 @@
|
|||
// Copyright 2023 The Tint 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.
|
||||
|
||||
#include "src/tint/cmd/helper.h"
|
||||
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace tint::cmd {
|
||||
namespace {
|
||||
|
||||
std::string TextureDimensionToString(tint::inspector::ResourceBinding::TextureDimension dim) {
|
||||
switch (dim) {
|
||||
case tint::inspector::ResourceBinding::TextureDimension::kNone:
|
||||
return "None";
|
||||
case tint::inspector::ResourceBinding::TextureDimension::k1d:
|
||||
return "1d";
|
||||
case tint::inspector::ResourceBinding::TextureDimension::k2d:
|
||||
return "2d";
|
||||
case tint::inspector::ResourceBinding::TextureDimension::k2dArray:
|
||||
return "2dArray";
|
||||
case tint::inspector::ResourceBinding::TextureDimension::k3d:
|
||||
return "3d";
|
||||
case tint::inspector::ResourceBinding::TextureDimension::kCube:
|
||||
return "Cube";
|
||||
case tint::inspector::ResourceBinding::TextureDimension::kCubeArray:
|
||||
return "CubeArray";
|
||||
}
|
||||
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
std::string SampledKindToString(tint::inspector::ResourceBinding::SampledKind kind) {
|
||||
switch (kind) {
|
||||
case tint::inspector::ResourceBinding::SampledKind::kFloat:
|
||||
return "Float";
|
||||
case tint::inspector::ResourceBinding::SampledKind::kUInt:
|
||||
return "UInt";
|
||||
case tint::inspector::ResourceBinding::SampledKind::kSInt:
|
||||
return "SInt";
|
||||
case tint::inspector::ResourceBinding::SampledKind::kUnknown:
|
||||
break;
|
||||
}
|
||||
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
std::string TexelFormatToString(tint::inspector::ResourceBinding::TexelFormat format) {
|
||||
switch (format) {
|
||||
case tint::inspector::ResourceBinding::TexelFormat::kR32Uint:
|
||||
return "R32Uint";
|
||||
case tint::inspector::ResourceBinding::TexelFormat::kR32Sint:
|
||||
return "R32Sint";
|
||||
case tint::inspector::ResourceBinding::TexelFormat::kR32Float:
|
||||
return "R32Float";
|
||||
case tint::inspector::ResourceBinding::TexelFormat::kBgra8Unorm:
|
||||
return "Bgra8Unorm";
|
||||
case tint::inspector::ResourceBinding::TexelFormat::kRgba8Unorm:
|
||||
return "Rgba8Unorm";
|
||||
case tint::inspector::ResourceBinding::TexelFormat::kRgba8Snorm:
|
||||
return "Rgba8Snorm";
|
||||
case tint::inspector::ResourceBinding::TexelFormat::kRgba8Uint:
|
||||
return "Rgba8Uint";
|
||||
case tint::inspector::ResourceBinding::TexelFormat::kRgba8Sint:
|
||||
return "Rgba8Sint";
|
||||
case tint::inspector::ResourceBinding::TexelFormat::kRg32Uint:
|
||||
return "Rg32Uint";
|
||||
case tint::inspector::ResourceBinding::TexelFormat::kRg32Sint:
|
||||
return "Rg32Sint";
|
||||
case tint::inspector::ResourceBinding::TexelFormat::kRg32Float:
|
||||
return "Rg32Float";
|
||||
case tint::inspector::ResourceBinding::TexelFormat::kRgba16Uint:
|
||||
return "Rgba16Uint";
|
||||
case tint::inspector::ResourceBinding::TexelFormat::kRgba16Sint:
|
||||
return "Rgba16Sint";
|
||||
case tint::inspector::ResourceBinding::TexelFormat::kRgba16Float:
|
||||
return "Rgba16Float";
|
||||
case tint::inspector::ResourceBinding::TexelFormat::kRgba32Uint:
|
||||
return "Rgba32Uint";
|
||||
case tint::inspector::ResourceBinding::TexelFormat::kRgba32Sint:
|
||||
return "Rgba32Sint";
|
||||
case tint::inspector::ResourceBinding::TexelFormat::kRgba32Float:
|
||||
return "Rgba32Float";
|
||||
case tint::inspector::ResourceBinding::TexelFormat::kNone:
|
||||
return "None";
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
std::string ResourceTypeToString(tint::inspector::ResourceBinding::ResourceType type) {
|
||||
switch (type) {
|
||||
case tint::inspector::ResourceBinding::ResourceType::kUniformBuffer:
|
||||
return "UniformBuffer";
|
||||
case tint::inspector::ResourceBinding::ResourceType::kStorageBuffer:
|
||||
return "StorageBuffer";
|
||||
case tint::inspector::ResourceBinding::ResourceType::kReadOnlyStorageBuffer:
|
||||
return "ReadOnlyStorageBuffer";
|
||||
case tint::inspector::ResourceBinding::ResourceType::kSampler:
|
||||
return "Sampler";
|
||||
case tint::inspector::ResourceBinding::ResourceType::kComparisonSampler:
|
||||
return "ComparisonSampler";
|
||||
case tint::inspector::ResourceBinding::ResourceType::kSampledTexture:
|
||||
return "SampledTexture";
|
||||
case tint::inspector::ResourceBinding::ResourceType::kMultisampledTexture:
|
||||
return "MultisampledTexture";
|
||||
case tint::inspector::ResourceBinding::ResourceType::kWriteOnlyStorageTexture:
|
||||
return "WriteOnlyStorageTexture";
|
||||
case tint::inspector::ResourceBinding::ResourceType::kDepthTexture:
|
||||
return "DepthTexture";
|
||||
case tint::inspector::ResourceBinding::ResourceType::kDepthMultisampledTexture:
|
||||
return "DepthMultisampledTexture";
|
||||
case tint::inspector::ResourceBinding::ResourceType::kExternalTexture:
|
||||
return "ExternalTexture";
|
||||
}
|
||||
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
std::string EntryPointStageToString(tint::inspector::PipelineStage stage) {
|
||||
switch (stage) {
|
||||
case tint::inspector::PipelineStage::kVertex:
|
||||
return "Vertex Shader";
|
||||
case tint::inspector::PipelineStage::kFragment:
|
||||
return "Fragment Shader";
|
||||
case tint::inspector::PipelineStage::kCompute:
|
||||
return "Compute Shader";
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
enum class InputFormat {
|
||||
kUnknown,
|
||||
kWgsl,
|
||||
kSpirvBin,
|
||||
kSpirvAsm,
|
||||
};
|
||||
|
||||
InputFormat InputFormatFromFilename(const std::string& filename) {
|
||||
auto input_format = InputFormat::kUnknown;
|
||||
|
||||
if (filename.size() > 5 && filename.substr(filename.size() - 5) == ".wgsl") {
|
||||
input_format = InputFormat::kWgsl;
|
||||
} else if (filename.size() > 4 && filename.substr(filename.size() - 4) == ".spv") {
|
||||
input_format = InputFormat::kSpirvBin;
|
||||
} else if (filename.size() > 7 && filename.substr(filename.size() - 7) == ".spvasm") {
|
||||
input_format = InputFormat::kSpirvAsm;
|
||||
}
|
||||
return input_format;
|
||||
}
|
||||
|
||||
/// Copies the content from the file named `input_file` to `buffer`,
|
||||
/// assuming each element in the file is of type `T`. If any error occurs,
|
||||
/// writes error messages to the standard error stream and returns false.
|
||||
/// Assumes the size of a `T` object is divisible by its required alignment.
|
||||
/// @returns true if we successfully read the file.
|
||||
template <typename T>
|
||||
bool ReadFile(const std::string& input_file, std::vector<T>* buffer) {
|
||||
if (!buffer) {
|
||||
std::cerr << "The buffer pointer was null" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
FILE* file = nullptr;
|
||||
#if defined(_MSC_VER)
|
||||
fopen_s(&file, input_file.c_str(), "rb");
|
||||
#else
|
||||
file = fopen(input_file.c_str(), "rb");
|
||||
#endif
|
||||
if (!file) {
|
||||
std::cerr << "Failed to open " << input_file << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
fseek(file, 0, SEEK_END);
|
||||
const auto file_size = static_cast<size_t>(ftell(file));
|
||||
if (0 != (file_size % sizeof(T))) {
|
||||
std::cerr << "File " << input_file
|
||||
<< " does not contain an integral number of objects: " << file_size
|
||||
<< " bytes in the file, require " << sizeof(T) << " bytes per object"
|
||||
<< std::endl;
|
||||
fclose(file);
|
||||
return false;
|
||||
}
|
||||
fseek(file, 0, SEEK_SET);
|
||||
|
||||
buffer->clear();
|
||||
buffer->resize(file_size / sizeof(T));
|
||||
|
||||
size_t bytes_read = fread(buffer->data(), 1, file_size, file);
|
||||
fclose(file);
|
||||
if (bytes_read != file_size) {
|
||||
std::cerr << "Failed to read " << input_file << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PrintBindings(tint::inspector::Inspector& inspector, const std::string& ep_name) {
|
||||
auto bindings = inspector.GetResourceBindings(ep_name);
|
||||
if (!inspector.error().empty()) {
|
||||
std::cerr << "Failed to get bindings from Inspector: " << inspector.error() << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
for (auto& binding : bindings) {
|
||||
std::cout << "\t[" << binding.bind_group << "][" << binding.binding << "]:" << std::endl;
|
||||
std::cout << "\t\t resource_type = " << ResourceTypeToString(binding.resource_type)
|
||||
<< std::endl;
|
||||
std::cout << "\t\t dim = " << TextureDimensionToString(binding.dim) << std::endl;
|
||||
std::cout << "\t\t sampled_kind = " << SampledKindToString(binding.sampled_kind)
|
||||
<< std::endl;
|
||||
std::cout << "\t\t image_format = " << TexelFormatToString(binding.image_format)
|
||||
<< std::endl;
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
[[noreturn]] void TintInternalCompilerErrorReporter(const tint::diag::List& diagnostics) {
|
||||
auto printer = tint::diag::Printer::create(stderr, true);
|
||||
tint::diag::Formatter{}.format(diagnostics, printer.get());
|
||||
tint::diag::Style bold_red{tint::diag::Color::kRed, true};
|
||||
constexpr const char* please_file_bug = R"(
|
||||
********************************************************************
|
||||
* The tint shader compiler has encountered an unexpected error. *
|
||||
* *
|
||||
* Please help us fix this issue by submitting a bug report at *
|
||||
* crbug.com/tint with the source program that triggered the bug. *
|
||||
********************************************************************
|
||||
)";
|
||||
printer->write(please_file_bug, bold_red);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void PrintWGSL(std::ostream& out, const tint::Program& program) {
|
||||
#if TINT_BUILD_WGSL_WRITER
|
||||
tint::writer::wgsl::Options options;
|
||||
auto result = tint::writer::wgsl::Generate(&program, options);
|
||||
out << std::endl << result.wgsl << std::endl;
|
||||
#else
|
||||
(void)out;
|
||||
(void)program;
|
||||
#endif
|
||||
}
|
||||
|
||||
ProgramInfo LoadProgramInfo(const LoadProgramOptions& opts) {
|
||||
std::unique_ptr<tint::Program> program;
|
||||
std::unique_ptr<tint::Source::File> source_file;
|
||||
|
||||
auto input_format = InputFormatFromFilename(opts.filename);
|
||||
switch (input_format) {
|
||||
case InputFormat::kUnknown: {
|
||||
std::cerr << "Unknown input format" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
case InputFormat::kWgsl: {
|
||||
#if TINT_BUILD_WGSL_READER
|
||||
std::vector<uint8_t> data;
|
||||
if (!ReadFile<uint8_t>(opts.filename, &data)) {
|
||||
exit(1);
|
||||
}
|
||||
source_file = std::make_unique<tint::Source::File>(
|
||||
opts.filename, std::string(data.begin(), data.end()));
|
||||
program = std::make_unique<tint::Program>(tint::reader::wgsl::Parse(source_file.get()));
|
||||
break;
|
||||
#else
|
||||
std::cerr << "Tint not built with the WGSL reader enabled" << std::endl;
|
||||
exit(1);
|
||||
#endif // TINT_BUILD_WGSL_READER
|
||||
}
|
||||
case InputFormat::kSpirvBin: {
|
||||
#if TINT_BUILD_SPV_READER
|
||||
std::vector<uint32_t> data;
|
||||
if (!ReadFile<uint32_t>(opts.filename, &data)) {
|
||||
exit(1);
|
||||
}
|
||||
program = std::make_unique<tint::Program>(
|
||||
tint::reader::spirv::Parse(data, opts.spirv_reader_options));
|
||||
break;
|
||||
#else
|
||||
std::cerr << "Tint not built with the SPIR-V reader enabled" << std::endl;
|
||||
exit(1);
|
||||
#endif // TINT_BUILD_SPV_READER
|
||||
}
|
||||
case InputFormat::kSpirvAsm: {
|
||||
#if TINT_BUILD_SPV_READER
|
||||
std::vector<char> text;
|
||||
if (!ReadFile<char>(opts.filename, &text)) {
|
||||
exit(1);
|
||||
}
|
||||
// Use Vulkan 1.1, since this is what Tint, internally, is expecting.
|
||||
spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_1);
|
||||
tools.SetMessageConsumer([](spv_message_level_t, const char*, const spv_position_t& pos,
|
||||
const char* msg) {
|
||||
std::cerr << (pos.line + 1) << ":" << (pos.column + 1) << ": " << msg << std::endl;
|
||||
});
|
||||
std::vector<uint32_t> data;
|
||||
if (!tools.Assemble(text.data(), text.size(), &data,
|
||||
SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS)) {
|
||||
exit(1);
|
||||
}
|
||||
program = std::make_unique<tint::Program>(
|
||||
tint::reader::spirv::Parse(data, opts.spirv_reader_options));
|
||||
break;
|
||||
#else
|
||||
std::cerr << "Tint not built with the SPIR-V reader enabled" << std::endl;
|
||||
exit(1);
|
||||
#endif // TINT_BUILD_SPV_READER
|
||||
}
|
||||
}
|
||||
|
||||
if (!program) {
|
||||
std::cerr << "Failed to parse input file: " << opts.filename << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
if (program->Diagnostics().count() > 0) {
|
||||
if (!program->IsValid() && input_format != InputFormat::kWgsl) {
|
||||
// Invalid program from a non-wgsl source. Print the WGSL, to help
|
||||
// understand the diagnostics.
|
||||
PrintWGSL(std::cout, *program);
|
||||
}
|
||||
|
||||
auto diag_printer = tint::diag::Printer::create(stderr, true);
|
||||
tint::diag::Formatter diag_formatter;
|
||||
diag_formatter.format(program->Diagnostics(), diag_printer.get());
|
||||
}
|
||||
|
||||
if (!program->IsValid()) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return ProgramInfo{
|
||||
std::move(program),
|
||||
std::move(source_file),
|
||||
};
|
||||
}
|
||||
|
||||
void PrintInspectorData(tint::inspector::Inspector& inspector) {
|
||||
auto entry_points = inspector.GetEntryPoints();
|
||||
if (!inspector.error().empty()) {
|
||||
std::cerr << "Failed to get entry points from Inspector: " << inspector.error()
|
||||
<< std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (auto& entry_point : entry_points) {
|
||||
std::cout << "Entry Point = " << entry_point.name << " ("
|
||||
<< EntryPointStageToString(entry_point.stage) << ")" << std::endl;
|
||||
|
||||
if (entry_point.workgroup_size) {
|
||||
std::cout << " Workgroup Size (" << entry_point.workgroup_size->x << ", "
|
||||
<< entry_point.workgroup_size->y << ", " << entry_point.workgroup_size->z
|
||||
<< ")" << std::endl;
|
||||
}
|
||||
|
||||
if (!entry_point.input_variables.empty()) {
|
||||
std::cout << " Input Variables:" << std::endl;
|
||||
|
||||
for (const auto& var : entry_point.input_variables) {
|
||||
std::cout << "\t";
|
||||
|
||||
if (var.has_location_attribute) {
|
||||
std::cout << "@location(" << var.location_attribute << ") ";
|
||||
}
|
||||
std::cout << var.name << std::endl;
|
||||
}
|
||||
}
|
||||
if (!entry_point.output_variables.empty()) {
|
||||
std::cout << " Output Variables:" << std::endl;
|
||||
|
||||
for (const auto& var : entry_point.output_variables) {
|
||||
std::cout << "\t";
|
||||
|
||||
if (var.has_location_attribute) {
|
||||
std::cout << "@location(" << var.location_attribute << ") ";
|
||||
}
|
||||
std::cout << var.name << std::endl;
|
||||
}
|
||||
}
|
||||
if (!entry_point.overrides.empty()) {
|
||||
std::cout << " Overrides:" << std::endl;
|
||||
|
||||
for (const auto& var : entry_point.overrides) {
|
||||
std::cout << "\tname: " << var.name << std::endl;
|
||||
std::cout << "\tid: " << var.id.value << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
auto bindings = inspector.GetResourceBindings(entry_point.name);
|
||||
if (!inspector.error().empty()) {
|
||||
std::cerr << "Failed to get bindings from Inspector: " << inspector.error()
|
||||
<< std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!bindings.empty()) {
|
||||
std::cout << " Bindings:" << std::endl;
|
||||
PrintBindings(inspector, entry_point.name);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void PrintInspectorBindings(tint::inspector::Inspector& inspector) {
|
||||
std::cout << std::string(80, '-') << std::endl;
|
||||
auto entry_points = inspector.GetEntryPoints();
|
||||
if (!inspector.error().empty()) {
|
||||
std::cerr << "Failed to get entry points from Inspector: " << inspector.error()
|
||||
<< std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (auto& entry_point : entry_points) {
|
||||
std::cout << "Entry Point = " << entry_point.name << std::endl;
|
||||
PrintBindings(inspector, entry_point.name);
|
||||
}
|
||||
std::cout << std::string(80, '-') << std::endl;
|
||||
}
|
||||
|
||||
} // namespace tint::cmd
|
|
@ -0,0 +1,67 @@
|
|||
// Copyright 2023 The Tint 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.
|
||||
|
||||
#ifndef SRC_TINT_CMD_HELPER_H_
|
||||
#define SRC_TINT_CMD_HELPER_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "tint/tint.h"
|
||||
|
||||
namespace tint::cmd {
|
||||
|
||||
/// Information on a loaded program
|
||||
struct ProgramInfo {
|
||||
/// The loaded program
|
||||
std::unique_ptr<tint::Program> program;
|
||||
/// The source file information
|
||||
std::unique_ptr<tint::Source::File> source_file;
|
||||
};
|
||||
|
||||
/// Reporter callback for internal tint errors
|
||||
/// @param diagnostics the diagnostics to emit
|
||||
[[noreturn]] void TintInternalCompilerErrorReporter(const tint::diag::List& diagnostics);
|
||||
|
||||
/// PrintWGSL writes the WGSL of the program to the provided ostream, if the
|
||||
/// WGSL writer is enabled, otherwise it does nothing.
|
||||
/// @param out the output stream to write the WGSL to
|
||||
/// @param program the program
|
||||
void PrintWGSL(std::ostream& out, const tint::Program& program);
|
||||
|
||||
/// Prints inspector data information to stderr
|
||||
/// @param inspector the inspector to print.
|
||||
void PrintInspectorData(tint::inspector::Inspector& inspector);
|
||||
|
||||
/// Prints inspector binding information to stderr
|
||||
/// @param inspector the inspector to print.
|
||||
void PrintInspectorBindings(tint::inspector::Inspector& inspector);
|
||||
|
||||
/// Options for the LoadProgramInfo call
|
||||
struct LoadProgramOptions {
|
||||
/// The file to be loaded
|
||||
std::string filename;
|
||||
#if TINT_BUILD_SPV_READER
|
||||
/// Spirv-reader options
|
||||
tint::reader::spirv::Options spirv_reader_options;
|
||||
#endif
|
||||
};
|
||||
|
||||
/// Loads the source and program information for the given file
|
||||
/// @param opts the loading options
|
||||
ProgramInfo LoadProgramInfo(const LoadProgramOptions& opts);
|
||||
|
||||
} // namespace tint::cmd
|
||||
|
||||
#endif // SRC_TINT_CMD_HELPER_H_
|
|
@ -0,0 +1,138 @@
|
|||
|
||||
// Copyright 2023 The Tint 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.
|
||||
|
||||
#if TINT_BUILD_SPV_READER
|
||||
#include "spirv-tools/libspirv.hpp"
|
||||
#endif // TINT_BUILD_SPV_READER
|
||||
|
||||
#include "src/tint/ast/module.h"
|
||||
#include "src/tint/cmd/helper.h"
|
||||
#include "src/tint/type/struct.h"
|
||||
#include "src/tint/utils/io/command.h"
|
||||
#include "src/tint/utils/string.h"
|
||||
#include "src/tint/utils/transform.h"
|
||||
#include "src/tint/val/val.h"
|
||||
#include "tint/tint.h"
|
||||
|
||||
namespace {
|
||||
|
||||
struct Options {
|
||||
bool show_help = false;
|
||||
|
||||
#if TINT_BUILD_SPV_READER
|
||||
tint::reader::spirv::Options spirv_reader_options;
|
||||
#endif
|
||||
|
||||
std::string input_filename;
|
||||
};
|
||||
|
||||
const char kUsage[] = R"(Usage: tint [options] <input-file>
|
||||
|
||||
options:
|
||||
-h -- This help text
|
||||
|
||||
)";
|
||||
|
||||
bool ParseArgs(const std::vector<std::string>& args, Options* opts) {
|
||||
for (size_t i = 1; i < args.size(); ++i) {
|
||||
const std::string& arg = args[i];
|
||||
if (arg == "-h" || arg == "--help") {
|
||||
opts->show_help = true;
|
||||
} else if (!arg.empty()) {
|
||||
if (arg[0] == '-') {
|
||||
std::cerr << "Unrecognized option: " << arg << std::endl;
|
||||
return false;
|
||||
}
|
||||
if (!opts->input_filename.empty()) {
|
||||
std::cerr << "More than one input file specified: '" << opts->input_filename
|
||||
<< "' and '" << arg << "'" << std::endl;
|
||||
return false;
|
||||
}
|
||||
opts->input_filename = arg;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, const char** argv) {
|
||||
std::vector<std::string> args(argv, argv + argc);
|
||||
Options options;
|
||||
|
||||
tint::SetInternalCompilerErrorReporter(&tint::cmd::TintInternalCompilerErrorReporter);
|
||||
|
||||
if (!ParseArgs(args, &options)) {
|
||||
std::cerr << "Failed to parse arguments." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (options.show_help) {
|
||||
std::cout << kUsage << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto diag_printer = tint::diag::Printer::create(stderr, true);
|
||||
tint::diag::Formatter diag_formatter;
|
||||
|
||||
std::unique_ptr<tint::Program> program;
|
||||
std::unique_ptr<tint::Source::File> source_file;
|
||||
|
||||
{
|
||||
tint::cmd::LoadProgramOptions opts;
|
||||
opts.filename = options.input_filename;
|
||||
#if TINT_BUILD_SPV_READER
|
||||
opts.spirv_reader_options = options.spirv_reader_options;
|
||||
#endif
|
||||
|
||||
auto info = tint::cmd::LoadProgramInfo(opts);
|
||||
program = std::move(info.program);
|
||||
source_file = std::move(info.source_file);
|
||||
}
|
||||
|
||||
tint::inspector::Inspector inspector(program.get());
|
||||
|
||||
if (!inspector.GetUsedExtensionNames().empty()) {
|
||||
std::cout << "Extensions:" << std::endl;
|
||||
for (const auto& name : inspector.GetUsedExtensionNames()) {
|
||||
std::cout << "\t" << name << std::endl;
|
||||
}
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
tint::cmd::PrintInspectorData(inspector);
|
||||
|
||||
bool has_struct = false;
|
||||
for (const auto* ty : program->Types()) {
|
||||
if (!ty->Is<tint::type::Struct>()) {
|
||||
continue;
|
||||
}
|
||||
has_struct = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (has_struct) {
|
||||
std::cout << "Structures" << std::endl;
|
||||
for (const auto* ty : program->Types()) {
|
||||
if (!ty->Is<tint::type::Struct>()) {
|
||||
continue;
|
||||
}
|
||||
const auto* s = ty->As<tint::type::Struct>();
|
||||
std::cout << s->Layout(program->Symbols()) << std::endl << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -34,6 +34,7 @@
|
|||
#endif // TINT_BUILD_SPV_READER
|
||||
|
||||
#include "src/tint/ast/module.h"
|
||||
#include "src/tint/cmd/helper.h"
|
||||
#include "src/tint/utils/io/command.h"
|
||||
#include "src/tint/utils/string.h"
|
||||
#include "src/tint/utils/transform.h"
|
||||
|
@ -48,22 +49,6 @@
|
|||
|
||||
namespace {
|
||||
|
||||
[[noreturn]] void TintInternalCompilerErrorReporter(const tint::diag::List& diagnostics) {
|
||||
auto printer = tint::diag::Printer::create(stderr, true);
|
||||
tint::diag::Formatter{}.format(diagnostics, printer.get());
|
||||
tint::diag::Style bold_red{tint::diag::Color::kRed, true};
|
||||
constexpr const char* please_file_bug = R"(
|
||||
********************************************************************
|
||||
* The tint shader compiler has encountered an unexpected error. *
|
||||
* *
|
||||
* Please help us fix this issue by submitting a bug report at *
|
||||
* crbug.com/tint with the source program that triggered the bug. *
|
||||
********************************************************************
|
||||
)";
|
||||
printer->write(please_file_bug, bold_red);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/// Prints the given hash value in a format string that the end-to-end test runner can parse.
|
||||
void PrintHash(uint32_t hash) {
|
||||
std::cout << "<<HASH: 0x" << std::hex << hash << ">>" << std::endl;
|
||||
|
@ -298,113 +283,6 @@ std::optional<uint64_t> parse_unsigned_number(std::string number) {
|
|||
return result;
|
||||
}
|
||||
|
||||
std::string TextureDimensionToString(tint::inspector::ResourceBinding::TextureDimension dim) {
|
||||
switch (dim) {
|
||||
case tint::inspector::ResourceBinding::TextureDimension::kNone:
|
||||
return "None";
|
||||
case tint::inspector::ResourceBinding::TextureDimension::k1d:
|
||||
return "1d";
|
||||
case tint::inspector::ResourceBinding::TextureDimension::k2d:
|
||||
return "2d";
|
||||
case tint::inspector::ResourceBinding::TextureDimension::k2dArray:
|
||||
return "2dArray";
|
||||
case tint::inspector::ResourceBinding::TextureDimension::k3d:
|
||||
return "3d";
|
||||
case tint::inspector::ResourceBinding::TextureDimension::kCube:
|
||||
return "Cube";
|
||||
case tint::inspector::ResourceBinding::TextureDimension::kCubeArray:
|
||||
return "CubeArray";
|
||||
}
|
||||
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
std::string SampledKindToString(tint::inspector::ResourceBinding::SampledKind kind) {
|
||||
switch (kind) {
|
||||
case tint::inspector::ResourceBinding::SampledKind::kFloat:
|
||||
return "Float";
|
||||
case tint::inspector::ResourceBinding::SampledKind::kUInt:
|
||||
return "UInt";
|
||||
case tint::inspector::ResourceBinding::SampledKind::kSInt:
|
||||
return "SInt";
|
||||
case tint::inspector::ResourceBinding::SampledKind::kUnknown:
|
||||
break;
|
||||
}
|
||||
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
std::string TexelFormatToString(tint::inspector::ResourceBinding::TexelFormat format) {
|
||||
switch (format) {
|
||||
case tint::inspector::ResourceBinding::TexelFormat::kR32Uint:
|
||||
return "R32Uint";
|
||||
case tint::inspector::ResourceBinding::TexelFormat::kR32Sint:
|
||||
return "R32Sint";
|
||||
case tint::inspector::ResourceBinding::TexelFormat::kR32Float:
|
||||
return "R32Float";
|
||||
case tint::inspector::ResourceBinding::TexelFormat::kBgra8Unorm:
|
||||
return "Bgra8Unorm";
|
||||
case tint::inspector::ResourceBinding::TexelFormat::kRgba8Unorm:
|
||||
return "Rgba8Unorm";
|
||||
case tint::inspector::ResourceBinding::TexelFormat::kRgba8Snorm:
|
||||
return "Rgba8Snorm";
|
||||
case tint::inspector::ResourceBinding::TexelFormat::kRgba8Uint:
|
||||
return "Rgba8Uint";
|
||||
case tint::inspector::ResourceBinding::TexelFormat::kRgba8Sint:
|
||||
return "Rgba8Sint";
|
||||
case tint::inspector::ResourceBinding::TexelFormat::kRg32Uint:
|
||||
return "Rg32Uint";
|
||||
case tint::inspector::ResourceBinding::TexelFormat::kRg32Sint:
|
||||
return "Rg32Sint";
|
||||
case tint::inspector::ResourceBinding::TexelFormat::kRg32Float:
|
||||
return "Rg32Float";
|
||||
case tint::inspector::ResourceBinding::TexelFormat::kRgba16Uint:
|
||||
return "Rgba16Uint";
|
||||
case tint::inspector::ResourceBinding::TexelFormat::kRgba16Sint:
|
||||
return "Rgba16Sint";
|
||||
case tint::inspector::ResourceBinding::TexelFormat::kRgba16Float:
|
||||
return "Rgba16Float";
|
||||
case tint::inspector::ResourceBinding::TexelFormat::kRgba32Uint:
|
||||
return "Rgba32Uint";
|
||||
case tint::inspector::ResourceBinding::TexelFormat::kRgba32Sint:
|
||||
return "Rgba32Sint";
|
||||
case tint::inspector::ResourceBinding::TexelFormat::kRgba32Float:
|
||||
return "Rgba32Float";
|
||||
case tint::inspector::ResourceBinding::TexelFormat::kNone:
|
||||
return "None";
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
std::string ResourceTypeToString(tint::inspector::ResourceBinding::ResourceType type) {
|
||||
switch (type) {
|
||||
case tint::inspector::ResourceBinding::ResourceType::kUniformBuffer:
|
||||
return "UniformBuffer";
|
||||
case tint::inspector::ResourceBinding::ResourceType::kStorageBuffer:
|
||||
return "StorageBuffer";
|
||||
case tint::inspector::ResourceBinding::ResourceType::kReadOnlyStorageBuffer:
|
||||
return "ReadOnlyStorageBuffer";
|
||||
case tint::inspector::ResourceBinding::ResourceType::kSampler:
|
||||
return "Sampler";
|
||||
case tint::inspector::ResourceBinding::ResourceType::kComparisonSampler:
|
||||
return "ComparisonSampler";
|
||||
case tint::inspector::ResourceBinding::ResourceType::kSampledTexture:
|
||||
return "SampledTexture";
|
||||
case tint::inspector::ResourceBinding::ResourceType::kMultisampledTexture:
|
||||
return "MultisampledTexture";
|
||||
case tint::inspector::ResourceBinding::ResourceType::kWriteOnlyStorageTexture:
|
||||
return "WriteOnlyStorageTexture";
|
||||
case tint::inspector::ResourceBinding::ResourceType::kDepthTexture:
|
||||
return "DepthTexture";
|
||||
case tint::inspector::ResourceBinding::ResourceType::kDepthMultisampledTexture:
|
||||
return "DepthMultisampledTexture";
|
||||
case tint::inspector::ResourceBinding::ResourceType::kExternalTexture:
|
||||
return "ExternalTexture";
|
||||
}
|
||||
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
bool ParseArgs(const std::vector<std::string>& args, Options* opts) {
|
||||
for (size_t i = 1; i < args.size(); ++i) {
|
||||
const std::string& arg = args[i];
|
||||
|
@ -565,54 +443,6 @@ bool ParseArgs(const std::vector<std::string>& args, Options* opts) {
|
|||
return true;
|
||||
}
|
||||
|
||||
/// Copies the content from the file named `input_file` to `buffer`,
|
||||
/// assuming each element in the file is of type `T`. If any error occurs,
|
||||
/// writes error messages to the standard error stream and returns false.
|
||||
/// Assumes the size of a `T` object is divisible by its required alignment.
|
||||
/// @returns true if we successfully read the file.
|
||||
template <typename T>
|
||||
bool ReadFile(const std::string& input_file, std::vector<T>* buffer) {
|
||||
if (!buffer) {
|
||||
std::cerr << "The buffer pointer was null" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
FILE* file = nullptr;
|
||||
#if defined(_MSC_VER)
|
||||
fopen_s(&file, input_file.c_str(), "rb");
|
||||
#else
|
||||
file = fopen(input_file.c_str(), "rb");
|
||||
#endif
|
||||
if (!file) {
|
||||
std::cerr << "Failed to open " << input_file << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
fseek(file, 0, SEEK_END);
|
||||
const auto file_size = static_cast<size_t>(ftell(file));
|
||||
if (0 != (file_size % sizeof(T))) {
|
||||
std::cerr << "File " << input_file
|
||||
<< " does not contain an integral number of objects: " << file_size
|
||||
<< " bytes in the file, require " << sizeof(T) << " bytes per object"
|
||||
<< std::endl;
|
||||
fclose(file);
|
||||
return false;
|
||||
}
|
||||
fseek(file, 0, SEEK_SET);
|
||||
|
||||
buffer->clear();
|
||||
buffer->resize(file_size / sizeof(T));
|
||||
|
||||
size_t bytes_read = fread(buffer->data(), 1, file_size, file);
|
||||
fclose(file);
|
||||
if (bytes_read != file_size) {
|
||||
std::cerr << "Failed to read " << input_file << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Writes the given `buffer` into the file named as `output_file` using the
|
||||
/// given `mode`. If `output_file` is empty or "-", writes to standard
|
||||
/// output. If any error occurs, returns false and outputs error message to
|
||||
|
@ -694,21 +524,6 @@ std::string Disassemble(const std::vector<uint32_t>& data) {
|
|||
}
|
||||
#endif // TINT_BUILD_SPV_WRITER
|
||||
|
||||
/// PrintWGSL writes the WGSL of the program to the provided ostream, if the
|
||||
/// WGSL writer is enabled, otherwise it does nothing.
|
||||
/// @param out the output stream to write the WGSL to
|
||||
/// @param program the program
|
||||
void PrintWGSL(std::ostream& out, const tint::Program& program) {
|
||||
#if TINT_BUILD_WGSL_WRITER
|
||||
tint::writer::wgsl::Options options;
|
||||
auto result = tint::writer::wgsl::Generate(&program, options);
|
||||
out << std::endl << result.wgsl << std::endl;
|
||||
#else
|
||||
(void)out;
|
||||
(void)program;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Generate SPIR-V code for a program.
|
||||
/// @param program the program to generate
|
||||
/// @param options the options that Tint was invoked with
|
||||
|
@ -721,7 +536,7 @@ bool GenerateSpirv(const tint::Program* program, const Options& options) {
|
|||
gen_options.generate_external_texture_bindings = true;
|
||||
auto result = tint::writer::spirv::Generate(program, gen_options);
|
||||
if (!result.success) {
|
||||
PrintWGSL(std::cerr, *program);
|
||||
tint::cmd::PrintWGSL(std::cerr, *program);
|
||||
std::cerr << "Failed to generate: " << result.error << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
@ -827,7 +642,7 @@ bool GenerateMsl(const tint::Program* program, const Options& options) {
|
|||
gen_options.generate_external_texture_bindings = true;
|
||||
auto result = tint::writer::msl::Generate(input_program, gen_options);
|
||||
if (!result.success) {
|
||||
PrintWGSL(std::cerr, *program);
|
||||
tint::cmd::PrintWGSL(std::cerr, *program);
|
||||
std::cerr << "Failed to generate: " << result.error << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
@ -888,7 +703,7 @@ bool GenerateHlsl(const tint::Program* program, const Options& options) {
|
|||
gen_options.root_constant_binding_point = options.hlsl_root_constant_binding_point;
|
||||
auto result = tint::writer::hlsl::Generate(program, gen_options);
|
||||
if (!result.success) {
|
||||
PrintWGSL(std::cerr, *program);
|
||||
tint::cmd::PrintWGSL(std::cerr, *program);
|
||||
std::cerr << "Failed to generate: " << result.error << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
@ -1025,7 +840,7 @@ bool GenerateGlsl(const tint::Program* program, const Options& options) {
|
|||
gen_options.generate_external_texture_bindings = true;
|
||||
auto result = tint::writer::glsl::Generate(prg, gen_options, entry_point_name);
|
||||
if (!result.success) {
|
||||
PrintWGSL(std::cerr, *prg);
|
||||
tint::cmd::PrintWGSL(std::cerr, *prg);
|
||||
std::cerr << "Failed to generate: " << result.error << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
@ -1087,7 +902,7 @@ int main(int argc, const char** argv) {
|
|||
std::vector<std::string> args(argv, argv + argc);
|
||||
Options options;
|
||||
|
||||
tint::SetInternalCompilerErrorReporter(&TintInternalCompilerErrorReporter);
|
||||
tint::SetInternalCompilerErrorReporter(&tint::cmd::TintInternalCompilerErrorReporter);
|
||||
|
||||
#if TINT_BUILD_WGSL_WRITER
|
||||
tint::Program::printer = [](const tint::Program* program) {
|
||||
|
@ -1254,102 +1069,18 @@ int main(int argc, const char** argv) {
|
|||
std::unique_ptr<tint::Program> program;
|
||||
std::unique_ptr<tint::Source::File> source_file;
|
||||
|
||||
enum class InputFormat {
|
||||
kUnknown,
|
||||
kWgsl,
|
||||
kSpirvBin,
|
||||
kSpirvAsm,
|
||||
};
|
||||
auto input_format = InputFormat::kUnknown;
|
||||
|
||||
if (options.input_filename.size() > 5 &&
|
||||
options.input_filename.substr(options.input_filename.size() - 5) == ".wgsl") {
|
||||
input_format = InputFormat::kWgsl;
|
||||
} else if (options.input_filename.size() > 4 &&
|
||||
options.input_filename.substr(options.input_filename.size() - 4) == ".spv") {
|
||||
input_format = InputFormat::kSpirvBin;
|
||||
} else if (options.input_filename.size() > 7 &&
|
||||
options.input_filename.substr(options.input_filename.size() - 7) == ".spvasm") {
|
||||
input_format = InputFormat::kSpirvAsm;
|
||||
}
|
||||
|
||||
switch (input_format) {
|
||||
case InputFormat::kUnknown: {
|
||||
std::cerr << "Unknown input format" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
case InputFormat::kWgsl: {
|
||||
#if TINT_BUILD_WGSL_READER
|
||||
std::vector<uint8_t> data;
|
||||
if (!ReadFile<uint8_t>(options.input_filename, &data)) {
|
||||
return 1;
|
||||
}
|
||||
source_file = std::make_unique<tint::Source::File>(
|
||||
options.input_filename, std::string(data.begin(), data.end()));
|
||||
program = std::make_unique<tint::Program>(tint::reader::wgsl::Parse(source_file.get()));
|
||||
break;
|
||||
#else
|
||||
std::cerr << "Tint not built with the WGSL reader enabled" << std::endl;
|
||||
return 1;
|
||||
#endif // TINT_BUILD_WGSL_READER
|
||||
}
|
||||
case InputFormat::kSpirvBin: {
|
||||
{
|
||||
tint::cmd::LoadProgramOptions opts;
|
||||
opts.filename = options.input_filename;
|
||||
#if TINT_BUILD_SPV_READER
|
||||
std::vector<uint32_t> data;
|
||||
if (!ReadFile<uint32_t>(options.input_filename, &data)) {
|
||||
return 1;
|
||||
}
|
||||
program = std::make_unique<tint::Program>(
|
||||
tint::reader::spirv::Parse(data, options.spirv_reader_options));
|
||||
break;
|
||||
#else
|
||||
std::cerr << "Tint not built with the SPIR-V reader enabled" << std::endl;
|
||||
return 1;
|
||||
#endif // TINT_BUILD_SPV_READER
|
||||
}
|
||||
case InputFormat::kSpirvAsm: {
|
||||
#if TINT_BUILD_SPV_READER
|
||||
std::vector<char> text;
|
||||
if (!ReadFile<char>(options.input_filename, &text)) {
|
||||
return 1;
|
||||
}
|
||||
// Use Vulkan 1.1, since this is what Tint, internally, is expecting.
|
||||
spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_1);
|
||||
tools.SetMessageConsumer([](spv_message_level_t, const char*, const spv_position_t& pos,
|
||||
const char* msg) {
|
||||
std::cerr << (pos.line + 1) << ":" << (pos.column + 1) << ": " << msg << std::endl;
|
||||
});
|
||||
std::vector<uint32_t> data;
|
||||
if (!tools.Assemble(text.data(), text.size(), &data,
|
||||
SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS)) {
|
||||
return 1;
|
||||
}
|
||||
program = std::make_unique<tint::Program>(
|
||||
tint::reader::spirv::Parse(data, options.spirv_reader_options));
|
||||
break;
|
||||
#else
|
||||
std::cerr << "Tint not built with the SPIR-V reader enabled" << std::endl;
|
||||
return 1;
|
||||
#endif // TINT_BUILD_SPV_READER
|
||||
}
|
||||
opts.spirv_reader_options = options.spirv_reader_options;
|
||||
#endif
|
||||
|
||||
auto info = tint::cmd::LoadProgramInfo(opts);
|
||||
program = std::move(info.program);
|
||||
source_file = std::move(info.source_file);
|
||||
}
|
||||
|
||||
if (!program) {
|
||||
std::cerr << "Failed to parse input file: " << options.input_filename << std::endl;
|
||||
return 1;
|
||||
}
|
||||
if (program->Diagnostics().count() > 0) {
|
||||
if (!program->IsValid() && input_format != InputFormat::kWgsl) {
|
||||
// Invalid program from a non-wgsl source. Print the WGSL, to help
|
||||
// understand the diagnostics.
|
||||
PrintWGSL(std::cout, *program);
|
||||
}
|
||||
diag_formatter.format(program->Diagnostics(), diag_printer.get());
|
||||
}
|
||||
|
||||
if (!program->IsValid()) {
|
||||
return 1;
|
||||
}
|
||||
if (options.parse_only) {
|
||||
return 1;
|
||||
}
|
||||
|
@ -1374,37 +1105,8 @@ int main(int argc, const char** argv) {
|
|||
#endif // TINT_BUILD_IR
|
||||
|
||||
tint::inspector::Inspector inspector(program.get());
|
||||
|
||||
if (options.dump_inspector_bindings) {
|
||||
std::cout << std::string(80, '-') << std::endl;
|
||||
auto entry_points = inspector.GetEntryPoints();
|
||||
if (!inspector.error().empty()) {
|
||||
std::cerr << "Failed to get entry points from Inspector: " << inspector.error()
|
||||
<< std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (auto& entry_point : entry_points) {
|
||||
auto bindings = inspector.GetResourceBindings(entry_point.name);
|
||||
if (!inspector.error().empty()) {
|
||||
std::cerr << "Failed to get bindings from Inspector: " << inspector.error()
|
||||
<< std::endl;
|
||||
return 1;
|
||||
}
|
||||
std::cout << "Entry Point = " << entry_point.name << std::endl;
|
||||
for (auto& binding : bindings) {
|
||||
std::cout << "\t[" << binding.bind_group << "][" << binding.binding
|
||||
<< "]:" << std::endl;
|
||||
std::cout << "\t\t resource_type = " << ResourceTypeToString(binding.resource_type)
|
||||
<< std::endl;
|
||||
std::cout << "\t\t dim = " << TextureDimensionToString(binding.dim) << std::endl;
|
||||
std::cout << "\t\t sampled_kind = " << SampledKindToString(binding.sampled_kind)
|
||||
<< std::endl;
|
||||
std::cout << "\t\t image_format = " << TexelFormatToString(binding.image_format)
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
std::cout << std::string(80, '-') << std::endl;
|
||||
tint::cmd::PrintInspectorBindings(inspector);
|
||||
}
|
||||
|
||||
tint::transform::Manager transform_manager;
|
||||
|
@ -1485,7 +1187,7 @@ int main(int argc, const char** argv) {
|
|||
|
||||
auto out = transform_manager.Run(program.get(), std::move(transform_inputs));
|
||||
if (!out.program.IsValid()) {
|
||||
PrintWGSL(std::cerr, out.program);
|
||||
tint::cmd::PrintWGSL(std::cerr, out.program);
|
||||
diag_formatter.format(out.program.Diagnostics(), diag_printer.get());
|
||||
return 1;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue