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 bool assembleSpirV (const SpirVAsmSource* program, std::vector<deUint32>* dst, SpirVProgramInfo* buildInfo)
     43 {
     44 	const spv_context	context		= spvContextCreate();
     45 	spv_binary			binary		= DE_NULL;
     46 	spv_diagnostic		diagnostic	= DE_NULL;
     47 
     48 	if (!context)
     49 		throw std::bad_alloc();
     50 
     51 	try
     52 	{
     53 		const std::string&	spvSource			= program->source;
     54 		const deUint64		compileStartTime	= deGetMicroseconds();
     55 		const spv_result_t	compileOk			= spvTextToBinary(context, spvSource.c_str(), spvSource.size(), &binary, &diagnostic);
     56 
     57 		buildInfo->source			= spvSource;
     58 		buildInfo->infoLog			= diagnostic? diagnostic->error : ""; // \todo [2015-07-13 pyry] Include debug log?
     59 		buildInfo->compileTimeUs	= deGetMicroseconds() - compileStartTime;
     60 		buildInfo->compileOk		= (compileOk == SPV_SUCCESS);
     61 
     62 		dst->resize(binary->wordCount);
     63 		std::copy(&binary->code[0], &binary->code[0] + binary->wordCount, dst->begin());
     64 
     65 		spvBinaryDestroy(binary);
     66 		spvDiagnosticDestroy(diagnostic);
     67 		spvContextDestroy(context);
     68 
     69 		return compileOk == SPV_SUCCESS;
     70 	}
     71 	catch (...)
     72 	{
     73 		spvBinaryDestroy(binary);
     74 		spvDiagnosticDestroy(diagnostic);
     75 		spvContextDestroy(context);
     76 
     77 		throw;
     78 	}
     79 }
     80 
     81 void disassembleSpirV (size_t binarySizeInWords, const deUint32* binary, std::ostream* dst)
     82 {
     83 	const spv_context	context		= spvContextCreate();
     84 	spv_text			text		= DE_NULL;
     85 	spv_diagnostic		diagnostic	= DE_NULL;
     86 
     87 	if (!context)
     88 		throw std::bad_alloc();
     89 
     90 	try
     91 	{
     92 		const spv_result_t	result	= spvBinaryToText(context, binary, binarySizeInWords, 0, &text, &diagnostic);
     93 
     94 		if (result != SPV_SUCCESS)
     95 			TCU_THROW(InternalError, "Disassembling SPIR-V failed");
     96 
     97 		*dst << text->str;
     98 
     99 		spvTextDestroy(text);
    100 		spvDiagnosticDestroy(diagnostic);
    101 		spvContextDestroy(context);
    102 	}
    103 	catch (...)
    104 	{
    105 		spvTextDestroy(text);
    106 		spvDiagnosticDestroy(diagnostic);
    107 		spvContextDestroy(context);
    108 
    109 		throw;
    110 	}
    111 }
    112 
    113 bool validateSpirV (size_t binarySizeInWords, const deUint32* binary, std::ostream* infoLog)
    114 {
    115 	const spv_context	context		= spvContextCreate();
    116 	spv_diagnostic		diagnostic	= DE_NULL;
    117 
    118 	try
    119 	{
    120 		spv_const_binary_t	cbinary		= { binary, binarySizeInWords };
    121 		const spv_result_t	valid		= spvValidate(context, &cbinary, &diagnostic);
    122 
    123 		if (diagnostic)
    124 			*infoLog << diagnostic->error;
    125 
    126 		spvDiagnosticDestroy(diagnostic);
    127 		spvContextDestroy(context);
    128 
    129 		return valid == SPV_SUCCESS;
    130 	}
    131 	catch (...)
    132 	{
    133 		spvDiagnosticDestroy(diagnostic);
    134 		spvContextDestroy(context);
    135 
    136 		throw;
    137 	}
    138 }
    139 
    140 #else // defined(DEQP_HAVE_SPIRV_TOOLS)
    141 
    142 bool assembleSpirV (const SpirVAsmSource*, std::vector<deUint32>*, SpirVProgramInfo*)
    143 {
    144 	TCU_THROW(NotSupportedError, "SPIR-V assembly not supported (DEQP_HAVE_SPIRV_TOOLS not defined)");
    145 }
    146 
    147 void disassembleSpirV (size_t, const deUint32*, std::ostream*)
    148 {
    149 	TCU_THROW(NotSupportedError, "SPIR-V disassembling not supported (DEQP_HAVE_SPIRV_TOOLS not defined)");
    150 }
    151 
    152 bool validateSpirV (size_t, const deUint32*, std::ostream*)
    153 {
    154 	TCU_THROW(NotSupportedError, "SPIR-V validation not supported (DEQP_HAVE_SPIRV_TOOLS not defined)");
    155 }
    156 
    157 #endif
    158 
    159 } // vk
    160