Home | History | Annotate | Download | only in vulkan
      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 
     34 namespace vk
     35 {
     36 
     37 using std::string;
     38 using std::vector;
     39 
     40 #if defined(DEQP_HAVE_SPIRV_TOOLS)
     41 
     42 static spv_target_env mapTargetSpvEnvironment(SpirvVersion spirvVersion)
     43 {
     44 	spv_target_env result = SPV_ENV_UNIVERSAL_1_0;
     45 
     46 	switch (spirvVersion)
     47 	{
     48 		case SPIRV_VERSION_1_0: result = SPV_ENV_UNIVERSAL_1_0; break;	//!< SPIR-V 1.0
     49 		case SPIRV_VERSION_1_1: result = SPV_ENV_UNIVERSAL_1_1; break;	//!< SPIR-V 1.1
     50 		case SPIRV_VERSION_1_2: result = SPV_ENV_UNIVERSAL_1_2; break;	//!< SPIR-V 1.2
     51 		case SPIRV_VERSION_1_3: result = SPV_ENV_UNIVERSAL_1_3; break;	//!< SPIR-V 1.3
     52 		default:				TCU_THROW(InternalError, "Unknown SPIR-V version");
     53 	}
     54 
     55 	return result;
     56 }
     57 
     58 bool assembleSpirV (const SpirVAsmSource* program, std::vector<deUint32>* dst, SpirVProgramInfo* buildInfo, SpirvVersion spirvVersion)
     59 {
     60 	const spv_context	context		= spvContextCreate(mapTargetSpvEnvironment(spirvVersion));
     61 	spv_binary			binary		= DE_NULL;
     62 	spv_diagnostic		diagnostic	= DE_NULL;
     63 
     64 	if (!context)
     65 		throw std::bad_alloc();
     66 
     67 	try
     68 	{
     69 		const std::string&	spvSource			= program->source;
     70 		const deUint64		compileStartTime	= deGetMicroseconds();
     71 		const spv_result_t	compileOk			= spvTextToBinary(context, spvSource.c_str(), spvSource.size(), &binary, &diagnostic);
     72 
     73 		buildInfo->source			= spvSource;
     74 		buildInfo->infoLog			= diagnostic? diagnostic->error : ""; // \todo [2015-07-13 pyry] Include debug log?
     75 		buildInfo->compileTimeUs	= deGetMicroseconds() - compileStartTime;
     76 		buildInfo->compileOk		= (compileOk == SPV_SUCCESS);
     77 
     78 		if (buildInfo->compileOk)
     79 		{
     80 			DE_ASSERT(binary->wordCount > 0);
     81 			dst->resize(binary->wordCount);
     82 			std::copy(&binary->code[0], &binary->code[0] + binary->wordCount, dst->begin());
     83 		}
     84 
     85 		spvBinaryDestroy(binary);
     86 		spvDiagnosticDestroy(diagnostic);
     87 		spvContextDestroy(context);
     88 
     89 		return compileOk == SPV_SUCCESS;
     90 	}
     91 	catch (...)
     92 	{
     93 		spvBinaryDestroy(binary);
     94 		spvDiagnosticDestroy(diagnostic);
     95 		spvContextDestroy(context);
     96 
     97 		throw;
     98 	}
     99 }
    100 
    101 void disassembleSpirV (size_t binarySizeInWords, const deUint32* binary, std::ostream* dst, SpirvVersion spirvVersion)
    102 {
    103 	const spv_context	context		= spvContextCreate(mapTargetSpvEnvironment(spirvVersion));
    104 	spv_text			text		= DE_NULL;
    105 	spv_diagnostic		diagnostic	= DE_NULL;
    106 
    107 	if (!context)
    108 		throw std::bad_alloc();
    109 
    110 	try
    111 	{
    112 		const spv_result_t	result	= spvBinaryToText(context, binary, binarySizeInWords, 0, &text, &diagnostic);
    113 
    114 		if (result != SPV_SUCCESS)
    115 			TCU_THROW(InternalError, "Disassembling SPIR-V failed");
    116 
    117 		*dst << text->str;
    118 
    119 		spvTextDestroy(text);
    120 		spvDiagnosticDestroy(diagnostic);
    121 		spvContextDestroy(context);
    122 	}
    123 	catch (...)
    124 	{
    125 		spvTextDestroy(text);
    126 		spvDiagnosticDestroy(diagnostic);
    127 		spvContextDestroy(context);
    128 
    129 		throw;
    130 	}
    131 }
    132 
    133 bool validateSpirV (size_t binarySizeInWords, const deUint32* binary, std::ostream* infoLog, SpirvVersion spirvVersion)
    134 {
    135 	const spv_context	context		= spvContextCreate(mapTargetSpvEnvironment(spirvVersion));
    136 	spv_diagnostic		diagnostic	= DE_NULL;
    137 
    138 	try
    139 	{
    140 		spv_const_binary_t	cbinary		= { binary, binarySizeInWords };
    141 		const spv_result_t	valid		= spvValidate(context, &cbinary, &diagnostic);
    142 
    143 		if (diagnostic)
    144 			*infoLog << diagnostic->error;
    145 
    146 		spvDiagnosticDestroy(diagnostic);
    147 		spvContextDestroy(context);
    148 
    149 		return valid == SPV_SUCCESS;
    150 	}
    151 	catch (...)
    152 	{
    153 		spvDiagnosticDestroy(diagnostic);
    154 		spvContextDestroy(context);
    155 
    156 		throw;
    157 	}
    158 }
    159 
    160 #else // defined(DEQP_HAVE_SPIRV_TOOLS)
    161 
    162 bool assembleSpirV (const SpirVAsmSource*, std::vector<deUint32>*, SpirVProgramInfo*, SpirvVersion)
    163 {
    164 	TCU_THROW(NotSupportedError, "SPIR-V assembly not supported (DEQP_HAVE_SPIRV_TOOLS not defined)");
    165 }
    166 
    167 void disassembleSpirV (size_t, const deUint32*, std::ostream*, SpirvVersion)
    168 {
    169 	TCU_THROW(NotSupportedError, "SPIR-V disassembling not supported (DEQP_HAVE_SPIRV_TOOLS not defined)");
    170 }
    171 
    172 bool validateSpirV (size_t, const deUint32*, std::ostream*, SpirvVersion)
    173 {
    174 	TCU_THROW(NotSupportedError, "SPIR-V validation not supported (DEQP_HAVE_SPIRV_TOOLS not defined)");
    175 }
    176 
    177 #endif
    178 
    179 } // vk
    180