blob: de47719cf3a5d17631dadde1f6faeb9e82c85319 [file] [log] [blame]
// Copyright 2020 The Clspv 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 <fstream>
#include <iostream>
#include <string>
#include "spirv-tools/libspirv.hpp"
#include "ReflectionParser.h"
void PrintUsage() {
const std::string help =
R"(Usage: clspv-reflection [--target-env <env>] [-o <outfile>] <infile>
Options:
--target-env <env> Specify the SPIR-V environment. Must be one of:
* spv1.0
* spv1.3
* spv1.5
* vulkan1.0
* vulkan1.1
* vulkan1.2
Default is spv1.0.
-o <outfile> Specify the output filename.
If no output file is specified, output goes to
stdout.
-d Disable validation.
)";
std::cout << help;
}
int main(const int argc, const char *const argv[]) {
std::string filename;
std::string outfile;
bool validate = true;
spv_target_env env(SPV_ENV_UNIVERSAL_1_0);
for (int i = 1; i < argc; ++i) {
const std::string option(argv[i]);
if (option == "-h" || option == "--help") {
PrintUsage();
return 0;
} else if (option == "--target-env") {
++i;
if (!spvParseTargetEnv(argv[i], &env)) {
std::cerr << "Error: invalid target env: " << argv[i] << "\n";
return -1;
}
switch (env) {
case SPV_ENV_UNIVERSAL_1_0:
case SPV_ENV_UNIVERSAL_1_3:
case SPV_ENV_UNIVERSAL_1_5:
case SPV_ENV_VULKAN_1_0:
case SPV_ENV_VULKAN_1_1:
case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
case SPV_ENV_VULKAN_1_2:
break;
default:
std::cerr << "Error: invalid target env: " << argv[i] << "\n";
return -1;
}
} else if (option == "-o") {
++i;
outfile = std::string(argv[i]);
} else if (option == "-d") {
validate = false;
} else if (option[0] == '-') {
std::cerr << "Error: unrecognized option '" << argv[i] << "'\n";
return -1;
} else {
if (!filename.empty()) {
std::cerr << "Error: too many positional arguments specified\n";
return -1;
}
filename = std::string(argv[i]);
}
}
if (filename.empty()) {
std::cerr << "Error: no binary file specified\n";
return -1;
}
// Read the binary.
std::ifstream str(filename.c_str(), std::ifstream::in |
std::ifstream::binary |
std::ifstream::ate);
if (!str) {
std::cerr << "Error: failed to open '" << filename << "'\n";
return -1;
}
std::streampos size = str.tellg();
std::vector<uint32_t> binary(size / 4, 0);
str.seekg(std::ios::beg);
str.read(reinterpret_cast<char *>(binary.data()), size);
str.close();
// TODO: worth forwarding some validator options (e.g. layout options)?
if (validate) {
// The parser assumes valid SPIR-V, so verify that assumption now.
spvtools::SpirvTools tools(env);
if (!tools.Validate(binary)) {
std::cerr << "Error: invalid binary\n";
return -1;
}
}
std::ostream *ostr = &std::cout;
if (!outfile.empty()) {
ostr = new std::ofstream(outfile.c_str());
if (!ostr) {
std::cerr << "Error: failed to open '" << outfile << "'\n";
delete ostr;
return -1;
}
}
bool ok = clspv::ParseReflection(binary, env, ostr);
if (!outfile.empty()) {
auto fstr = reinterpret_cast<std::ofstream *>(ostr);
fstr->close();
delete fstr;
}
if (!ok) {
std::cerr << "Error: failed to parse reflection info\n";
return -1;
}
return 0;
}