Path: blob/main/libshaderc_util/src/spirv_tools_wrapper.cc
1560 views
// Copyright 2016 The Shaderc Authors. All rights reserved.1//2// Licensed under the Apache License, Version 2.0 (the "License");3// you may not use this file except in compliance with the License.4// You may obtain a copy of the License at5//6// http://www.apache.org/licenses/LICENSE-2.07//8// Unless required by applicable law or agreed to in writing, software9// distributed under the License is distributed on an "AS IS" BASIS,10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.11// See the License for the specific language governing permissions and12// limitations under the License.1314#include "libshaderc_util/spirv_tools_wrapper.h"1516#include <algorithm>17#include <sstream>1819#include "spirv-tools/libspirv.hpp"20#include "spirv-tools/optimizer.hpp"2122namespace shaderc_util {2324namespace {2526// Gets the corresponding target environment used in SPIRV-Tools.27spv_target_env GetSpirvToolsTargetEnv(Compiler::TargetEnv env,28Compiler::TargetEnvVersion version) {29switch (env) {30case Compiler::TargetEnv::Vulkan:31switch (version) {32case Compiler::TargetEnvVersion::Default:33return SPV_ENV_VULKAN_1_0;34case Compiler::TargetEnvVersion::Vulkan_1_0:35return SPV_ENV_VULKAN_1_0;36case Compiler::TargetEnvVersion::Vulkan_1_1:37return SPV_ENV_VULKAN_1_1;38case Compiler::TargetEnvVersion::Vulkan_1_2:39return SPV_ENV_VULKAN_1_2;40case Compiler::TargetEnvVersion::Vulkan_1_3:41return SPV_ENV_VULKAN_1_3;42default:43break;44}45break;46case Compiler::TargetEnv::OpenGL:47return SPV_ENV_OPENGL_4_5;48case Compiler::TargetEnv::OpenGLCompat:49// Errors out before getting here. But the compiler wants us to handle50// enum anyway.51return SPV_ENV_OPENGL_4_5;52}53assert(false && "unexpected target environment or version");54return SPV_ENV_VULKAN_1_0;55}5657} // anonymous namespace5859bool SpirvToolsDisassemble(Compiler::TargetEnv env,60Compiler::TargetEnvVersion version,61const std::vector<uint32_t>& binary,62std::string* text_or_error) {63spvtools::SpirvTools tools(GetSpirvToolsTargetEnv(env, version));64std::ostringstream oss;65tools.SetMessageConsumer([&oss](spv_message_level_t, const char*,66const spv_position_t& position,67const char* message) {68oss << position.index << ": " << message;69});70const bool success =71tools.Disassemble(binary, text_or_error,72SPV_BINARY_TO_TEXT_OPTION_INDENT |73SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);74if (!success) {75*text_or_error = oss.str();76}77return success;78}7980bool SpirvToolsAssemble(Compiler::TargetEnv env,81Compiler::TargetEnvVersion version,82const string_piece assembly, spv_binary* binary,83std::string* errors) {84auto spvtools_context =85spvContextCreate(GetSpirvToolsTargetEnv(env, version));86spv_diagnostic spvtools_diagnostic = nullptr;8788*binary = nullptr;89errors->clear();9091const bool success =92spvTextToBinary(spvtools_context, assembly.data(), assembly.size(),93binary, &spvtools_diagnostic) == SPV_SUCCESS;94if (!success) {95std::ostringstream oss;96oss << spvtools_diagnostic->position.line + 1 << ":"97<< spvtools_diagnostic->position.column + 1 << ": "98<< spvtools_diagnostic->error;99*errors = oss.str();100}101102spvDiagnosticDestroy(spvtools_diagnostic);103spvContextDestroy(spvtools_context);104105return success;106}107108bool SpirvToolsOptimize(Compiler::TargetEnv env,109Compiler::TargetEnvVersion version,110const std::vector<PassId>& enabled_passes,111spvtools::OptimizerOptions& optimizer_options,112std::vector<uint32_t>* binary, std::string* errors) {113errors->clear();114if (enabled_passes.empty()) return true;115if (std::all_of(116enabled_passes.cbegin(), enabled_passes.cend(),117[](const PassId& pass) { return pass == PassId::kNullPass; })) {118return true;119}120121spvtools::ValidatorOptions val_opts;122// This allows flexible memory layout for HLSL.123val_opts.SetSkipBlockLayout(true);124// This allows HLSL legalization regarding resources.125val_opts.SetRelaxLogicalPointer(true);126// This uses relaxed rules for pre-legalized HLSL.127val_opts.SetBeforeHlslLegalization(true);128129// Set additional optimizer options.130optimizer_options.set_validator_options(val_opts);131optimizer_options.set_run_validator(true);132133spvtools::Optimizer optimizer(GetSpirvToolsTargetEnv(env, version));134135std::ostringstream oss;136optimizer.SetMessageConsumer(137[&oss](spv_message_level_t, const char*, const spv_position_t&,138const char* message) { oss << message << "\n"; });139140for (const auto& pass : enabled_passes) {141switch (pass) {142case PassId::kLegalizationPasses:143optimizer.RegisterLegalizationPasses();144break;145case PassId::kPerformancePasses:146optimizer.RegisterPerformancePasses();147break;148case PassId::kSizePasses:149optimizer.RegisterSizePasses();150break;151case PassId::kNullPass:152// We actually don't need to do anything for null pass.153break;154case PassId::kStripDebugInfo:155optimizer.RegisterPass(spvtools::CreateStripDebugInfoPass());156break;157case PassId::kCompactIds:158optimizer.RegisterPass(spvtools::CreateCompactIdsPass());159break;160}161}162163if (!optimizer.Run(binary->data(), binary->size(), binary,164optimizer_options)) {165*errors = oss.str();166return false;167}168return true;169}170171} // namespace shaderc_util172173174