1 // Copyright 2021 The Dawn Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "dawn_native/SpirvValidation.h" 16 17 #include "dawn_native/Device.h" 18 19 #include <spirv-tools/libspirv.hpp> 20 #include <sstream> 21 22 namespace dawn_native { 23 ValidateSpirv(DeviceBase * device,const std::vector<uint32_t> & spirv,bool dumpSpirv)24 MaybeError ValidateSpirv(DeviceBase* device, 25 const std::vector<uint32_t>& spirv, 26 bool dumpSpirv) { 27 spvtools::SpirvTools spirvTools(SPV_ENV_VULKAN_1_1); 28 spirvTools.SetMessageConsumer([device](spv_message_level_t level, const char*, 29 const spv_position_t& position, 30 const char* message) { 31 WGPULoggingType wgpuLogLevel; 32 switch (level) { 33 case SPV_MSG_FATAL: 34 case SPV_MSG_INTERNAL_ERROR: 35 case SPV_MSG_ERROR: 36 wgpuLogLevel = WGPULoggingType_Error; 37 break; 38 case SPV_MSG_WARNING: 39 wgpuLogLevel = WGPULoggingType_Warning; 40 break; 41 case SPV_MSG_INFO: 42 wgpuLogLevel = WGPULoggingType_Info; 43 break; 44 default: 45 wgpuLogLevel = WGPULoggingType_Error; 46 break; 47 } 48 49 std::ostringstream ss; 50 ss << "SPIRV line " << position.index << ": " << message << std::endl; 51 device->EmitLog(wgpuLogLevel, ss.str().c_str()); 52 }); 53 54 const bool valid = spirvTools.Validate(spirv); 55 if (dumpSpirv || !valid) { 56 std::ostringstream dumpedMsg; 57 std::string disassembly; 58 if (spirvTools.Disassemble( 59 spirv, &disassembly, 60 SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES | SPV_BINARY_TO_TEXT_OPTION_INDENT)) { 61 dumpedMsg << "/* Dumped generated SPIRV disassembly */" << std::endl << disassembly; 62 } else { 63 dumpedMsg << "/* Failed to disassemble generated SPIRV */"; 64 } 65 device->EmitLog(WGPULoggingType_Info, dumpedMsg.str().c_str()); 66 } 67 68 DAWN_INVALID_IF(!valid, 69 "Produced invalid SPIRV. Please file a bug at https://crbug.com/tint."); 70 71 return {}; 72 } 73 74 } // namespace dawn_native 75