mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-08-13 07:29:07 +00:00
This CL enable using f16 override, and also fix related tests in Dawn and Tint. Bug: tint:1473, tint:1502 Change-Id: I8336770e8a73e5023c1aba224b7b5f21692fbaa6 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/124544 Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: Austin Eng <enga@chromium.org> Commit-Queue: Zhaoming Jiang <zhaoming.jiang@intel.com> Reviewed-by: Corentin Wallez <cwallez@chromium.org>
519 lines
19 KiB
C++
519 lines
19 KiB
C++
// 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 <iostream>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#if TINT_BUILD_SPV_READER
|
|
#include "spirv-tools/libspirv.hpp"
|
|
#endif
|
|
|
|
namespace tint::cmd {
|
|
namespace {
|
|
|
|
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;
|
|
}
|
|
|
|
std::string EntryPointStageToString(tint::inspector::PipelineStage stage) {
|
|
switch (stage) {
|
|
case tint::inspector::PipelineStage::kVertex:
|
|
return "vertex";
|
|
case tint::inspector::PipelineStage::kFragment:
|
|
return "fragment";
|
|
case tint::inspector::PipelineStage::kCompute:
|
|
return "compute";
|
|
}
|
|
return "Unknown";
|
|
}
|
|
|
|
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 ComponentTypeToString(tint::inspector::ComponentType type) {
|
|
switch (type) {
|
|
case tint::inspector::ComponentType::kUnknown:
|
|
return "unknown";
|
|
case tint::inspector::ComponentType::kF32:
|
|
return "f32";
|
|
case tint::inspector::ComponentType::kU32:
|
|
return "u32";
|
|
case tint::inspector::ComponentType::kI32:
|
|
return "i32";
|
|
case tint::inspector::ComponentType::kF16:
|
|
return "f16";
|
|
}
|
|
return "unknown";
|
|
}
|
|
|
|
std::string CompositionTypeToString(tint::inspector::CompositionType type) {
|
|
switch (type) {
|
|
case tint::inspector::CompositionType::kUnknown:
|
|
return "unknown";
|
|
case tint::inspector::CompositionType::kScalar:
|
|
return "scalar";
|
|
case tint::inspector::CompositionType::kVec2:
|
|
return "vec2";
|
|
case tint::inspector::CompositionType::kVec3:
|
|
return "vec3";
|
|
case tint::inspector::CompositionType::kVec4:
|
|
return "vec4";
|
|
}
|
|
return "unknown";
|
|
}
|
|
|
|
std::string InterpolationTypeToString(tint::inspector::InterpolationType type) {
|
|
switch (type) {
|
|
case tint::inspector::InterpolationType::kUnknown:
|
|
return "unknown";
|
|
case tint::inspector::InterpolationType::kPerspective:
|
|
return "perspective";
|
|
case tint::inspector::InterpolationType::kLinear:
|
|
return "linear";
|
|
case tint::inspector::InterpolationType::kFlat:
|
|
return "flat";
|
|
}
|
|
return "unknown";
|
|
}
|
|
|
|
std::string InterpolationSamplingToString(tint::inspector::InterpolationSampling type) {
|
|
switch (type) {
|
|
case tint::inspector::InterpolationSampling::kUnknown:
|
|
return "unknown";
|
|
case tint::inspector::InterpolationSampling::kNone:
|
|
return "none";
|
|
case tint::inspector::InterpolationSampling::kCenter:
|
|
return "center";
|
|
case tint::inspector::InterpolationSampling::kCentroid:
|
|
return "centroid";
|
|
case tint::inspector::InterpolationSampling::kSample:
|
|
return "sample";
|
|
}
|
|
return "unknown";
|
|
}
|
|
|
|
std::string OverrideTypeToString(tint::inspector::Override::Type type) {
|
|
switch (type) {
|
|
case tint::inspector::Override::Type::kBool:
|
|
return "bool";
|
|
case tint::inspector::Override::Type::kFloat32:
|
|
return "f32";
|
|
case tint::inspector::Override::Type::kFloat16:
|
|
return "f16";
|
|
case tint::inspector::Override::Type::kUint32:
|
|
return "u32";
|
|
case tint::inspector::Override::Type::kInt32:
|
|
return "i32";
|
|
}
|
|
return "unknown";
|
|
}
|
|
|
|
} // namespace tint::cmd
|