1 // Copyright 2020 The SwiftShader Authors. All Rights Reserved. 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 #ifndef sw_SpirvShaderDebug_hpp 16 #define sw_SpirvShaderDebug_hpp 17 18 #include "SpirvShader.hpp" 19 20 // Enable this to print verbose debug messages as each SPIR-V instructon is 21 // executed. Very handy for performing text diffs when the thread count is 22 // reduced to 1 and execution is deterministic. 23 #define SPIRV_SHADER_ENABLE_DBG 0 24 25 // Enable this to write a GraphViz dot file containing a graph of the shader's 26 // control flow to the given file path. Helpful for diagnosing control-flow 27 // related issues. 28 #if 0 29 # define SPIRV_SHADER_CFG_GRAPHVIZ_DOT_FILEPATH "swiftshader_%d.dot" 30 #endif 31 32 #if SPIRV_SHADER_ENABLE_DBG 33 # define SPIRV_SHADER_DBG(fmt, ...) rr::Print(fmt "\n", ##__VA_ARGS__) 34 # include "spirv-tools/libspirv.h" 35 namespace spvtools { 36 // Function implemented in third_party/SPIRV-Tools/source/disassemble.cpp 37 // but with no public header. 38 std::string spvInstructionBinaryToText(const spv_target_env env, 39 const uint32_t *inst_binary, 40 const size_t inst_word_count, 41 const uint32_t *binary, 42 const size_t word_count, 43 const uint32_t options); 44 45 } // namespace spvtools 46 #else 47 # define SPIRV_SHADER_DBG(...) 48 #endif // SPIRV_SHADER_ENABLE_DBG 49 50 #ifdef ENABLE_RR_PRINT 51 namespace rr { 52 template<> 53 struct PrintValue::Ty<sw::SpirvShader::Object::ID> 54 { fmtrr::PrintValue::Ty55 static inline std::string fmt(sw::SpirvShader::Object::ID v) { return "Object<" + std::to_string(v.value()) + ">"; } valrr::PrintValue::Ty56 static inline std::vector<Value *> val(sw::SpirvShader::Object::ID v) { return {}; } 57 }; 58 template<> 59 struct PrintValue::Ty<sw::SpirvShader::Type::ID> 60 { fmtrr::PrintValue::Ty61 static inline std::string fmt(sw::SpirvShader::Type::ID v) { return "Type<" + std::to_string(v.value()) + ">"; } valrr::PrintValue::Ty62 static inline std::vector<Value *> val(sw::SpirvShader::Type::ID v) { return {}; } 63 }; 64 template<> 65 struct PrintValue::Ty<sw::SpirvShader::Block::ID> 66 { fmtrr::PrintValue::Ty67 static inline std::string fmt(sw::SpirvShader::Block::ID v) { return "Block<" + std::to_string(v.value()) + ">"; } valrr::PrintValue::Ty68 static inline std::vector<Value *> val(sw::SpirvShader::Block::ID v) { return {}; } 69 }; 70 71 template<> 72 struct PrintValue::Ty<sw::Intermediate> 73 { fmtrr::PrintValue::Ty74 static inline std::string fmt(const sw::Intermediate &v, uint32_t i) 75 { 76 switch(v.typeHint) 77 { 78 case sw::Intermediate::TypeHint::Float: 79 return PrintValue::Ty<sw::SIMD::Float>::fmt(v.Float(i)); 80 case sw::Intermediate::TypeHint::Int: 81 return PrintValue::Ty<sw::SIMD::Int>::fmt(v.Int(i)); 82 case sw::Intermediate::TypeHint::UInt: 83 return PrintValue::Ty<sw::SIMD::UInt>::fmt(v.UInt(i)); 84 } 85 return ""; 86 } 87 valrr::PrintValue::Ty88 static inline std::vector<Value *> val(const sw::Intermediate &v, uint32_t i) 89 { 90 switch(v.typeHint) 91 { 92 case sw::Intermediate::TypeHint::Float: 93 return PrintValue::Ty<sw::SIMD::Float>::val(v.Float(i)); 94 case sw::Intermediate::TypeHint::Int: 95 return PrintValue::Ty<sw::SIMD::Int>::val(v.Int(i)); 96 case sw::Intermediate::TypeHint::UInt: 97 return PrintValue::Ty<sw::SIMD::UInt>::val(v.UInt(i)); 98 } 99 return {}; 100 } 101 fmtrr::PrintValue::Ty102 static inline std::string fmt(const sw::Intermediate &v) 103 { 104 if(v.componentCount == 1) 105 { 106 return fmt(v, 0); 107 } 108 109 std::string out = "["; 110 for(uint32_t i = 0; i < v.componentCount; i++) 111 { 112 if(i > 0) { out += ", "; } 113 out += std::to_string(i) + ": "; 114 out += fmt(v, i); 115 } 116 return out + "]"; 117 } 118 valrr::PrintValue::Ty119 static inline std::vector<Value *> val(const sw::Intermediate &v) 120 { 121 std::vector<Value *> out; 122 for(uint32_t i = 0; i < v.componentCount; i++) 123 { 124 auto vals = val(v, i); 125 out.insert(out.end(), vals.begin(), vals.end()); 126 } 127 return out; 128 } 129 }; 130 131 template<> 132 struct PrintValue::Ty<sw::SpirvShader::Operand> 133 { fmtrr::PrintValue::Ty134 static inline std::string fmt(const sw::SpirvShader::Operand &v) 135 { 136 return (v.intermediate != nullptr) ? PrintValue::Ty<sw::Intermediate>::fmt(*v.intermediate) : PrintValue::Ty<sw::SIMD::UInt>::fmt(v.UInt(0)); 137 } 138 valrr::PrintValue::Ty139 static inline std::vector<Value *> val(const sw::SpirvShader::Operand &v) 140 { 141 return (v.intermediate != nullptr) ? PrintValue::Ty<sw::Intermediate>::val(*v.intermediate) : PrintValue::Ty<sw::SIMD::UInt>::val(v.UInt(0)); 142 } 143 }; 144 } // namespace rr 145 #endif // ENABLE_RR_PRINT 146 147 #endif // sw_SpirvShaderDebug_hpp 148