1/*------------------------------------------------------------------------- 2 * Vulkan CTS Framework 3 * -------------------- 4 * 5 * Copyright (c) 2015 Google Inc. 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 *//*! 20 * \file 21 * \brief SPIR-V assembly to binary. 22 *//*--------------------------------------------------------------------*/ 23 24#include "vkSpirVAsm.hpp" 25#include "vkSpirVProgram.hpp" 26#include "deClock.h" 27 28#include <algorithm> 29 30#if defined(DEQP_HAVE_SPIRV_TOOLS) 31# include "spirv-tools/libspirv.h" 32#endif 33 34namespace vk 35{ 36 37using std::string; 38using std::vector; 39 40#if defined(DEQP_HAVE_SPIRV_TOOLS) 41 42static const spv_target_env s_defaultEnvironment = SPV_ENV_VULKAN_1_0; 43 44bool assembleSpirV (const SpirVAsmSource* program, std::vector<deUint32>* dst, SpirVProgramInfo* buildInfo) 45{ 46 const spv_context context = spvContextCreate(s_defaultEnvironment); 47 spv_binary binary = DE_NULL; 48 spv_diagnostic diagnostic = DE_NULL; 49 50 if (!context) 51 throw std::bad_alloc(); 52 53 try 54 { 55 const std::string& spvSource = program->source; 56 const deUint64 compileStartTime = deGetMicroseconds(); 57 const spv_result_t compileOk = spvTextToBinary(context, spvSource.c_str(), spvSource.size(), &binary, &diagnostic); 58 59 buildInfo->source = spvSource; 60 buildInfo->infoLog = diagnostic? diagnostic->error : ""; // \todo [2015-07-13 pyry] Include debug log? 61 buildInfo->compileTimeUs = deGetMicroseconds() - compileStartTime; 62 buildInfo->compileOk = (compileOk == SPV_SUCCESS); 63 64 if (buildInfo->compileOk) 65 { 66 DE_ASSERT(binary->wordCount > 0); 67 dst->resize(binary->wordCount); 68 std::copy(&binary->code[0], &binary->code[0] + binary->wordCount, dst->begin()); 69 } 70 71 spvBinaryDestroy(binary); 72 spvDiagnosticDestroy(diagnostic); 73 spvContextDestroy(context); 74 75 return compileOk == SPV_SUCCESS; 76 } 77 catch (...) 78 { 79 spvBinaryDestroy(binary); 80 spvDiagnosticDestroy(diagnostic); 81 spvContextDestroy(context); 82 83 throw; 84 } 85} 86 87void disassembleSpirV (size_t binarySizeInWords, const deUint32* binary, std::ostream* dst) 88{ 89 const spv_context context = spvContextCreate(s_defaultEnvironment); 90 spv_text text = DE_NULL; 91 spv_diagnostic diagnostic = DE_NULL; 92 93 if (!context) 94 throw std::bad_alloc(); 95 96 try 97 { 98 const spv_result_t result = spvBinaryToText(context, binary, binarySizeInWords, 0, &text, &diagnostic); 99 100 if (result != SPV_SUCCESS) 101 TCU_THROW(InternalError, "Disassembling SPIR-V failed"); 102 103 *dst << text->str; 104 105 spvTextDestroy(text); 106 spvDiagnosticDestroy(diagnostic); 107 spvContextDestroy(context); 108 } 109 catch (...) 110 { 111 spvTextDestroy(text); 112 spvDiagnosticDestroy(diagnostic); 113 spvContextDestroy(context); 114 115 throw; 116 } 117} 118 119bool validateSpirV (size_t binarySizeInWords, const deUint32* binary, std::ostream* infoLog) 120{ 121 const spv_context context = spvContextCreate(s_defaultEnvironment); 122 spv_diagnostic diagnostic = DE_NULL; 123 124 try 125 { 126 spv_const_binary_t cbinary = { binary, binarySizeInWords }; 127 const spv_result_t valid = spvValidate(context, &cbinary, &diagnostic); 128 129 if (diagnostic) 130 *infoLog << diagnostic->error; 131 132 spvDiagnosticDestroy(diagnostic); 133 spvContextDestroy(context); 134 135 return valid == SPV_SUCCESS; 136 } 137 catch (...) 138 { 139 spvDiagnosticDestroy(diagnostic); 140 spvContextDestroy(context); 141 142 throw; 143 } 144} 145 146#else // defined(DEQP_HAVE_SPIRV_TOOLS) 147 148bool assembleSpirV (const SpirVAsmSource*, std::vector<deUint32>*, SpirVProgramInfo*) 149{ 150 TCU_THROW(NotSupportedError, "SPIR-V assembly not supported (DEQP_HAVE_SPIRV_TOOLS not defined)"); 151} 152 153void disassembleSpirV (size_t, const deUint32*, std::ostream*) 154{ 155 TCU_THROW(NotSupportedError, "SPIR-V disassembling not supported (DEQP_HAVE_SPIRV_TOOLS not defined)"); 156} 157 158bool validateSpirV (size_t, const deUint32*, std::ostream*) 159{ 160 TCU_THROW(NotSupportedError, "SPIR-V validation not supported (DEQP_HAVE_SPIRV_TOOLS not defined)"); 161} 162 163#endif 164 165} // vk 166