blob: 876fedc8e2a9f70cf57bf05a0f94d3d7078ce284 [file] [log] [blame]
/*-------------------------------------------------------------------------
* Vulkan CTS Framework
* --------------------
*
* Copyright (c) 2015 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*//*!
* \file
* \brief SPIR-V assembly to binary.
*//*--------------------------------------------------------------------*/
#include "vkSpirVAsm.hpp"
#include "vkSpirVProgram.hpp"
#include "deClock.h"
#include <algorithm>
#if defined(DEQP_HAVE_SPIRV_TOOLS)
# include "spirv-tools/libspirv.h"
#endif
namespace vk
{
using std::string;
using std::vector;
#if defined(DEQP_HAVE_SPIRV_TOOLS)
static const spv_target_env s_defaultEnvironment = SPV_ENV_VULKAN_1_0;
bool assembleSpirV (const SpirVAsmSource* program, std::vector<deUint32>* dst, SpirVProgramInfo* buildInfo)
{
const spv_context context = spvContextCreate(s_defaultEnvironment);
spv_binary binary = DE_NULL;
spv_diagnostic diagnostic = DE_NULL;
if (!context)
throw std::bad_alloc();
try
{
const std::string& spvSource = program->source;
const deUint64 compileStartTime = deGetMicroseconds();
const spv_result_t compileOk = spvTextToBinary(context, spvSource.c_str(), spvSource.size(), &binary, &diagnostic);
buildInfo->source = spvSource;
buildInfo->infoLog = diagnostic? diagnostic->error : ""; // \todo [2015-07-13 pyry] Include debug log?
buildInfo->compileTimeUs = deGetMicroseconds() - compileStartTime;
buildInfo->compileOk = (compileOk == SPV_SUCCESS);
if (buildInfo->compileOk)
{
DE_ASSERT(binary->wordCount > 0);
dst->resize(binary->wordCount);
std::copy(&binary->code[0], &binary->code[0] + binary->wordCount, dst->begin());
}
spvBinaryDestroy(binary);
spvDiagnosticDestroy(diagnostic);
spvContextDestroy(context);
return compileOk == SPV_SUCCESS;
}
catch (...)
{
spvBinaryDestroy(binary);
spvDiagnosticDestroy(diagnostic);
spvContextDestroy(context);
throw;
}
}
void disassembleSpirV (size_t binarySizeInWords, const deUint32* binary, std::ostream* dst)
{
const spv_context context = spvContextCreate(s_defaultEnvironment);
spv_text text = DE_NULL;
spv_diagnostic diagnostic = DE_NULL;
if (!context)
throw std::bad_alloc();
try
{
const spv_result_t result = spvBinaryToText(context, binary, binarySizeInWords, 0, &text, &diagnostic);
if (result != SPV_SUCCESS)
TCU_THROW(InternalError, "Disassembling SPIR-V failed");
*dst << text->str;
spvTextDestroy(text);
spvDiagnosticDestroy(diagnostic);
spvContextDestroy(context);
}
catch (...)
{
spvTextDestroy(text);
spvDiagnosticDestroy(diagnostic);
spvContextDestroy(context);
throw;
}
}
bool validateSpirV (size_t binarySizeInWords, const deUint32* binary, std::ostream* infoLog)
{
const spv_context context = spvContextCreate(s_defaultEnvironment);
spv_diagnostic diagnostic = DE_NULL;
try
{
spv_const_binary_t cbinary = { binary, binarySizeInWords };
const spv_result_t valid = spvValidate(context, &cbinary, &diagnostic);
if (diagnostic)
*infoLog << diagnostic->error;
spvDiagnosticDestroy(diagnostic);
spvContextDestroy(context);
return valid == SPV_SUCCESS;
}
catch (...)
{
spvDiagnosticDestroy(diagnostic);
spvContextDestroy(context);
throw;
}
}
#else // defined(DEQP_HAVE_SPIRV_TOOLS)
bool assembleSpirV (const SpirVAsmSource*, std::vector<deUint32>*, SpirVProgramInfo*)
{
TCU_THROW(NotSupportedError, "SPIR-V assembly not supported (DEQP_HAVE_SPIRV_TOOLS not defined)");
}
void disassembleSpirV (size_t, const deUint32*, std::ostream*)
{
TCU_THROW(NotSupportedError, "SPIR-V disassembling not supported (DEQP_HAVE_SPIRV_TOOLS not defined)");
}
bool validateSpirV (size_t, const deUint32*, std::ostream*)
{
TCU_THROW(NotSupportedError, "SPIR-V validation not supported (DEQP_HAVE_SPIRV_TOOLS not defined)");
}
#endif
} // vk