This allows hand-written assembly tests.
It follows the same philosophy as glslang, and allows spirv to be
assembled prior to running the tests or at test time.
Change-Id: I1110fcd4f5713b50274502e73703bd1ba2fd372f
# glslang
add_subdirectory(external/glslang)
+# spirv-tools
+add_subdirectory(external/spirv-tools)
+
include_directories(${PNG_INCLUDE_PATH})
message(STATUS "DEQP_TARGET_NAME = ${DEQP_TARGET_NAME}")
--- /dev/null
+#cmake file for spirv-tools
+
+if (NOT DE_DEFS)
+ message(FATAL_ERROR "Include Defs.cmake")
+endif ()
+
+# Assume build inside Android source tree
+set(DEFAULT_SPIRV_TOOLS_SRC_PATH "../spirv-tools")
+
+set(SPIRV_TOOLS_SRC_PATH ${DEFAULT_SPIRV_TOOLS_SRC_PATH} CACHE STRING "Path to spirv-tools source tree")
+if (IS_ABSOLUTE ${SPIRV_TOOLS_SRC_PATH})
+ set(SPIRV_TOOLS_ABS_PATH ${SPIRV_TOOLS_SRC_PATH})
+else ()
+ set(SPIRV_TOOLS_ABS_PATH "${CMAKE_SOURCE_DIR}/${SPIRV_TOOLS_SRC_PATH}")
+endif ()
+
+if (EXISTS ${SPIRV_TOOLS_ABS_PATH}/source/opcode.cpp)
+ message(STATUS "spirv-tools found; building with DEQP_HAVE_SPIRV_TOOLS")
+ set(CMAKE_C_FLAGS ${DE_3RD_PARTY_C_FLAGS})
+ set(CMAKE_CXX_FLAGS ${DE_3RD_PARTY_CXX_FLAGS})
+
+ set(DEQP_HAVE_SPIRV_TOOLS ON PARENT_SCOPE)
+ set(SPIRV_SKIP_EXECUTABLES ON)
+ add_subdirectory(${SPIRV_TOOLS_ABS_PATH} spirv-tools)
+else()
+ message(STATUS "spirv-tools not found; SPIR-V assembly not available")
+ set(DEQP_HAVE_SPIRV_TOOLS OFF PARENT_SCOPE)
+endif()
$ cd .. # assuming you were in 'deqp' source directory
$ git clone https://github.com/KhronosGroup/glslang.git glslang
+spirv-tools is optional, but enables SPIRV assembly. Check out spirv-tools
+from the google branch of the gitlab repository next to 'deqp':
+
+$ cd .. # assuming you were in 'deqp' source directory
+$ git clone -b google https://gitlab.khronos.org/spirv/spirv-tools.git
+
I.e the final directory structure should look like this:
src/
deqp/
glslang/
+ spirv-tools/
After downloading all dependencies, please follow instructions at
http://source.android.com/devices/graphics/build-tests.html
vkDeviceUtil.hpp
vkGlslToSpirV.cpp
vkGlslToSpirV.hpp
+ vkSpirVAsm.hpp
+ vkSpirVAsm.cpp
+ vkSpirVProgram.hpp
+ vkSpirVProgram.cpp
vkBinaryRegistry.cpp
vkBinaryRegistry.hpp
vkNullDriver.cpp
set(VKUTIL_LIBS ${VKUTIL_LIBS} ${GLSLANG_LIBRARY})
endif ()
+if(DEQP_HAVE_SPIRV_TOOLS)
+ include_directories(${spirv-tools_SOURCE_DIR}/include)
+ include_directories(${spirv-tools_SOURCE_DIR}/external/include)
+
+ add_definitions(-DDEQP_HAVE_SPIRV_TOOLS=1)
+ set(VKUTIL_LIBS ${VKUTIL_LIBS} SPIRV-TOOLS)
+endif()
+
add_library(vkutil STATIC ${VKUTIL_SRCS})
target_link_libraries(vkutil ${VKUTIL_LIBS})
#include "vkPrograms.hpp"
#include "vkGlslToSpirV.hpp"
+#include "vkSpirVAsm.hpp"
#include "vkRefUtil.hpp"
#include "tcuTestLog.hpp"
TCU_THROW(NotSupportedError, "Unsupported program format");
}
+ProgramBinary* assembleProgram (const SpirVAsmSource& program, SpirVProgramInfo* buildInfo)
+{
+ vector<deUint8> binary;
+ assembleSpirV(&program, &binary, buildInfo);
+ return new ProgramBinary(PROGRAM_FORMAT_SPIRV, binary.size(), &binary[0]);
+}
+
Move<VkShaderModule> createShaderModule (const DeviceInterface& deviceInterface, VkDevice device, const ProgramBinary& binary, VkShaderModuleCreateFlags flags)
{
if (binary.getFormat() == PROGRAM_FORMAT_SPIRV)
#include "vkDefs.hpp"
#include "vkRef.hpp"
+#include "vkSpirVProgram.hpp"
#include "gluShaderProgram.hpp"
#include "deUniquePtr.hpp"
#include "deSTLUtil.hpp"
return *m_programs.find(name)->second;
}
-typedef ProgramCollection<glu::ProgramSources> SourceCollection;
+typedef vk::ProgramCollection<glu::ProgramSources> GlslSourceCollection;
+typedef vk::ProgramCollection<vk::SpirVAsmSource> SpirVAsmCollection;
+
+struct SourceCollections
+{
+ GlslSourceCollection glslSources;
+ SpirVAsmCollection spirvAsmSources;
+};
+
typedef ProgramCollection<ProgramBinary> BinaryCollection;
// \todo [2015-03-13 pyry] Likely need BinaryBuilder abstraction for this
ProgramBinary* buildProgram (const glu::ProgramSources& program, ProgramFormat binaryFormat, glu::ShaderProgramInfo* buildInfo);
+ProgramBinary* assembleProgram (const vk::SpirVAsmSource& program, SpirVProgramInfo* buildInfo);
Move<VkShaderModule> createShaderModule (const DeviceInterface& deviceInterface, VkDevice device, const ProgramBinary& binary, VkShaderModuleCreateFlags flags);
} // vk
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief SPIR-V assembly to binary.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkSpirVAsm.hpp"
+#include "vkSpirVProgram.hpp"
+#include "deArrayUtil.hpp"
+#include "deMemory.h"
+#include "deClock.h"
+#include "qpDebugOut.h"
+
+#if defined(DEQP_HAVE_SPIRV_TOOLS)
+# include "deSingleton.h"
+
+# include "libspirv/libspirv.h"
+#endif
+
+namespace vk
+{
+
+using std::string;
+using std::vector;
+
+#if defined(DEQP_HAVE_SPIRV_TOOLS)
+
+namespace
+{
+static volatile deSingletonState s_spirvInitState = DE_SINGLETON_STATE_NOT_INITIALIZED;
+static spv_opcode_table s_spirvOpcodeTable;
+static spv_operand_table s_spirvOperandTable;
+static spv_ext_inst_table s_spirvExtInstTable;
+
+void initSpirVTools (void*)
+{
+ spvCheck(spvOpcodeTableGet(&s_spirvOpcodeTable) != SPV_SUCCESS,
+ TCU_THROW(InternalError, "Cannot get opcode table for assembly"));
+
+ spvCheck(spvOperandTableGet(&s_spirvOperandTable) != SPV_SUCCESS,
+ TCU_THROW(InternalError, "Cannot get operand table for assembly"));
+
+ spvCheck(spvExtInstTableGet(&s_spirvExtInstTable) != SPV_SUCCESS,
+ TCU_THROW(InternalError, "Cannot get external instruction table for assembly"));
+}
+
+void prepareSpirvTools (void)
+{
+ deInitSingleton(&s_spirvInitState, initSpirVTools, DE_NULL);
+}
+
+} // anonymous
+
+void assembleSpirV (const SpirVAsmSource* program, std::vector<deUint8>* dst, SpirVProgramInfo* buildInfo)
+{
+ prepareSpirvTools();
+
+ const std::string& spvSource = program->program.str();
+ spv_binary binary = DE_NULL;
+ spv_diagnostic diagnostic = DE_NULL;
+ const deUint64 compileStartTime = deGetMicroseconds();
+ const spv_result_t compileOk = spvTextToBinary(spvSource.c_str(), spvSource.size(), s_spirvOpcodeTable, s_spirvOperandTable, s_spirvExtInstTable, &binary, &diagnostic);
+
+ {
+ buildInfo->source = program;
+ buildInfo->infoLog = diagnostic? diagnostic->error : ""; // \todo [2015-07-13 pyry] Include debug log?
+ buildInfo->compileTimeUs = deGetMicroseconds() - compileStartTime;
+ buildInfo->compileOk = (compileOk == SPV_SUCCESS);
+ }
+
+ if (compileOk != SPV_SUCCESS)
+ TCU_FAIL("Failed to compile shader");
+
+ dst->resize((int)binary->wordCount * sizeof(deUint32));
+#if (DE_ENDIANNESS == DE_LITTLE_ENDIAN)
+ deMemcpy(&(*dst)[0], &binary->code[0], dst->size());
+#else
+# error "Big-endian not supported"
+#endif
+ spvBinaryDestroy(binary);
+ spvDiagnosticDestroy(diagnostic);
+ return;
+}
+
+#else // defined(DEQP_HAVE_SPIRV_TOOLS)
+
+void assembleSpirV (const SpirvProgram* program, std::vector<deUint8>* dst, SpirvProgramInfo* buildInfo)
+{
+ TCU_THROW(NotSupportedError, "SPIR-V assembly not supported (DEQP_HAVE_SPIRV_TOOLS not defined)");
+}
+
+#endif
+
+} // vk
--- /dev/null
+#ifndef _VKSPIRVASM_HPP
+#define _VKSPIRVASM_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief SPIR-V assembly to binary.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkDefs.hpp"
+#include "vkPrograms.hpp"
+
+namespace vk
+{
+
+//! Assemble SPIR-V program. Will fail with NotSupportedError if compiler is not available.
+void assembleSpirV (const SpirVAsmSource* program, std::vector<deUint8>* dst, SpirVProgramInfo* buildInfo);
+
+} // vk
+
+#endif // _VKSPIRVASM_HPP
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief Spirv program and binary info.
+ *//*--------------------------------------------------------------------*/
+
+#include "vkSpirVProgram.hpp"
+
+#include "tcuTestLog.hpp"
+
+namespace vk
+{
+
+tcu::TestLog& operator<< (tcu::TestLog& log, const SpirVProgramInfo& shaderInfo)
+{
+ log << tcu::TestLog::ShaderProgram(shaderInfo.compileOk , shaderInfo.infoLog) << tcu::TestLog::EndShaderProgram;
+
+ // Write statistics
+ log << tcu::TestLog::Float( "SpirVAssemblyTime",
+ "SpirV assembly time",
+ "ms", QP_KEY_TAG_TIME, (float)shaderInfo.compileTimeUs / 1000.0f);
+ return log;
+}
+
+tcu::TestLog& operator<< (tcu::TestLog& log, const SpirVAsmSource& source)
+{
+ log << tcu::TestLog::KernelSource(source.program.str());
+
+ return log;
+}
+
+} // vk
--- /dev/null
+#ifndef _VKSPIPVROGRAM_HPP
+#define _VKSPIPVROGRAM_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan CTS Framework
+ * --------------------
+ *
+ * Copyright (c) 2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*!
+ * \file
+ * \brief SPIR-V program and binary info.
+ *//*--------------------------------------------------------------------*/
+
+#include <sstream>
+
+#include "vkDefs.hpp"
+#include "tcuTestLog.hpp"
+
+namespace vk
+{
+
+struct SpirVAsmSource
+{
+ SpirVAsmSource& operator<<(const char* val)
+ {
+ program << val;
+ return *this;
+ }
+ std::ostringstream program;
+};
+
+struct SpirVProgramInfo
+{
+ SpirVProgramInfo()
+ : source (DE_NULL)
+ , compileTimeUs (0)
+ , compileOk (false)
+ {
+ }
+
+ const SpirVAsmSource* source;
+ std::string infoLog;
+ deUint64 compileTimeUs;
+ bool compileOk;
+};
+
+tcu::TestLog& operator<< (tcu::TestLog& log, const SpirVProgramInfo& shaderInfo);
+tcu::TestLog& operator<< (tcu::TestLog& log, const SpirVAsmSource& program);
+
+}
+
+#endif // _VKSPIVPROGRAM_HPP
return tcu::TestStatus::pass("Creating sampler succeeded");
}
-void createShaderProgs (SourceCollection& dst)
+void createShaderProgs (SourceCollections& dst)
{
- dst.add("test") << glu::VertexSource(
+ dst.glslSources.add("test") << glu::VertexSource(
"#version 300 es\n"
"in highp vec4 a_position;\n"
"void main (void) { gl_Position = a_position; }\n");
return tcu::TestStatus::pass("Creating shader module succeeded");
}
-void createTriangleProgs (SourceCollection& dst)
+void createTriangleAsmProgs (SourceCollections& dst)
{
- dst.add("vert") << glu::VertexSource(
+ dst.spirvAsmSources.add("vert") <<
+ " OpSource ESSL 300\n"
+ " OpCapability Shader\n"
+ "%1 = OpExtInstImport \"GLSL.std.450\"\n"
+ " OpMemoryModel Logical GLSL450\n"
+ " OpEntryPoint Vertex %4 \"main\"\n"
+ " OpName %4 \"main\"\n"
+ " OpName %10 \"gl_Position\"\n"
+ " OpName %12 \"a_position\"\n"
+ " OpName %16 \"gl_VertexID\"\n"
+ " OpName %17 \"gl_InstanceID\"\n"
+ " OpDecorate %10 BuiltIn Position\n"
+ " OpDecorate %12 Location 0\n"
+ " OpDecorate %16 BuiltIn VertexId\n"
+ " OpDecorate %16 NoStaticUse\n"
+ " OpDecorate %17 BuiltIn InstanceId\n"
+ " OpDecorate %17 NoStaticUse\n"
+ "%2 = OpTypeVoid\n"
+ "%3 = OpTypeFunction %2\n"
+ "%7 = OpTypeFloat 32\n"
+ "%8 = OpTypeVector %7 4\n"
+ "%9 = OpTypePointer Output %8\n"
+ "%10 = OpVariable %9 Output\n"
+ "%11 = OpTypePointer Input %8\n"
+ "%12 = OpVariable %11 Input\n"
+ "%14 = OpTypeInt 32 1\n"
+ "%15 = OpTypePointer Input %14\n"
+ "%16 = OpVariable %15 Input\n"
+ "%17 = OpVariable %15 Input\n"
+ "%4 = OpFunction %2 None %3\n"
+ "%5 = OpLabel\n"
+ "%13 = OpLoad %8 %12\n"
+ " OpStore %10 %13\n"
+ " OpBranch %6\n"
+ "%6 = OpLabel\n"
+ " OpReturn\n"
+ " OpFunctionEnd\n";
+ dst.spirvAsmSources.add("frag") <<
+ " OpSource ESSL 300\n"
+ " OpCapability Shader\n"
+ "%1 = OpExtInstImport \"GLSL.std.450\"\n"
+ " OpMemoryModel Logical GLSL450\n"
+ " OpEntryPoint Fragment %4 \"main\"\n"
+ " OpExecutionMode %4 OriginLowerLeft\n"
+ " OpName %4 \"main\"\n"
+ " OpName %10 \"o_color\"\n"
+ " OpDecorate %10 RelaxedPrecision\n"
+ " OpDecorate %10 Location 0\n"
+ "%2 = OpTypeVoid\n"
+ "%3 = OpTypeFunction %2\n"
+ "%7 = OpTypeFloat 32\n"
+ "%8 = OpTypeVector %7 4\n"
+ "%9 = OpTypePointer Output %8\n"
+ "%10 = OpVariable %9 Output\n"
+ "%11 = OpConstant %7 1065353216\n"
+ "%12 = OpConstant %7 0\n"
+ "%13 = OpConstantComposite %8 %11 %12 %11 %11\n"
+ "%4 = OpFunction %2 None %3\n"
+ "%5 = OpLabel\n"
+ " OpStore %10 %13\n"
+ " OpBranch %6\n"
+ "%6 = OpLabel\n"
+ " OpReturn\n"
+ " OpFunctionEnd\n";
+}
+
+void createTriangleProgs (SourceCollections& dst)
+{
+ dst.glslSources.add("vert") << glu::VertexSource(
"#version 300 es\n"
"layout(location = 0) in highp vec4 a_position;\n"
"void main (void) { gl_Position = a_position; }\n");
- dst.add("frag") << glu::FragmentSource(
+ dst.glslSources.add("frag") << glu::FragmentSource(
"#version 300 es\n"
"layout(location = 0) out lowp vec4 o_color;\n"
"void main (void) { o_color = vec4(1.0, 0.0, 1.0, 1.0); }\n");
addFunctionCase (smokeTests.get(), "create_sampler", "", createSamplerTest);
addFunctionCaseWithPrograms (smokeTests.get(), "create_shader", "", createShaderProgs, createShaderModuleTest);
addFunctionCaseWithPrograms (smokeTests.get(), "triangle", "", createTriangleProgs, renderTriangleTest);
+ addFunctionCaseWithPrograms (smokeTests.get(), "asm_triangle", "", createTriangleAsmProgs, renderTriangleTest);
return smokeTests.release();
}
}
};
+namespace // anonymous
+{
+
+vk::ProgramBinary* compileProgram (const glu::ProgramSources& source, glu::ShaderProgramInfo* buildInfo)
+{
+ return vk::buildProgram(source, vk::PROGRAM_FORMAT_SPIRV, buildInfo);
+}
+
+vk::ProgramBinary* compileProgram (const vk::SpirVAsmSource& source, vk::SpirVProgramInfo* buildInfo)
+{
+ return vk::assembleProgram(source, buildInfo);
+}
+
+void writeVerboseLogs (const glu::ShaderProgramInfo& buildInfo)
+{
+ for (size_t shaderNdx = 0; shaderNdx < buildInfo.shaders.size(); shaderNdx++)
+ {
+ const glu::ShaderInfo& shaderInfo = buildInfo.shaders[shaderNdx];
+ const char* const shaderName = getShaderTypeName(shaderInfo.type);
+
+ tcu::print("%s source:\n---\n%s\n---\n", shaderName, shaderInfo.source.c_str());
+ tcu::print("%s compile log:\n---\n%s\n---\n", shaderName, shaderInfo.infoLog.c_str());
+ }
+}
+
+void writeVerboseLogs (const vk::SpirVProgramInfo& buildInfo)
+{
+ tcu::print("source:\n---\n%s\n---\n", buildInfo.source->program.str().c_str());
+ tcu::print("compile log:\n---\n%s\n---\n", buildInfo.infoLog.c_str());
+}
+
+template <typename InfoType, typename IteratorType>
+void buildProgram (const std::string& casePath,
+ bool printLogs,
+ IteratorType iter,
+ BuildMode mode,
+ BuildStats* stats,
+ vk::BinaryRegistryReader* reader,
+ vk::BinaryRegistryWriter* writer)
+{
+ InfoType buildInfo;
+ try
+ {
+ const vk::ProgramIdentifier progId (casePath, iter.getName());
+ const UniquePtr<vk::ProgramBinary> binary (compileProgram(iter.getProgram(), &buildInfo));
+
+ if (mode == BUILDMODE_BUILD)
+ writer->storeProgram(progId, *binary);
+ else
+ {
+ DE_ASSERT(mode == BUILDMODE_VERIFY);
+
+ const UniquePtr<vk::ProgramBinary> storedBinary (reader->loadProgram(progId));
+
+ if (binary->getSize() != storedBinary->getSize())
+ throw tcu::Exception("Binary size doesn't match");
+
+ if (deMemCmp(binary->getBinary(), storedBinary->getBinary(), binary->getSize()))
+ throw tcu::Exception("Binary contents don't match");
+ }
+
+ tcu::print(" OK: %s\n", iter.getName().c_str());
+ stats->numSucceeded += 1;
+ }
+ catch (const std::exception& e)
+ {
+ tcu::print(" ERROR: %s: %s\n", iter.getName().c_str(), e.what());
+ if (printLogs)
+ {
+ writeVerboseLogs(buildInfo);
+ }
+ stats->numFailed += 1;
+ }
+}
+
+} // anonymous
BuildStats buildPrograms (tcu::TestContext& testCtx, const std::string& dstPath, BuildMode mode, bool verbose)
{
const UniquePtr<tcu::TestPackageRoot> root (createRoot(testCtx));
{
const TestCase* const testCase = dynamic_cast<TestCase*>(iterator.getNode());
const string casePath = iterator.getNodePath();
- vk::SourceCollection progs;
+ vk::SourceCollections progs;
tcu::print("%s\n", casePath.c_str());
testCase->initPrograms(progs);
- for (vk::SourceCollection::Iterator progIter = progs.begin(); progIter != progs.end(); ++progIter)
+ for (vk::GlslSourceCollection::Iterator progIter = progs.glslSources.begin(); progIter != progs.glslSources.end(); ++progIter)
+ {
+ buildProgram<glu::ShaderProgramInfo, vk::GlslSourceCollection::Iterator>(casePath, printLogs, progIter, mode, &stats, reader.get(), writer.get());
+ }
+
+ for (vk::SpirVAsmCollection::Iterator progIter = progs.spirvAsmSources.begin(); progIter != progs.spirvAsmSources.end(); ++progIter)
{
- glu::ShaderProgramInfo buildInfo;
-
- try
- {
- const vk::ProgramIdentifier progId (casePath, progIter.getName());
- const UniquePtr<vk::ProgramBinary> binary (vk::buildProgram(progIter.getProgram(), vk::PROGRAM_FORMAT_SPIRV, &buildInfo));
-
- if (mode == BUILDMODE_BUILD)
- writer->storeProgram(progId, *binary);
- else
- {
- DE_ASSERT(mode == BUILDMODE_VERIFY);
-
- const UniquePtr<vk::ProgramBinary> storedBinary (reader->loadProgram(progId));
-
- if (binary->getSize() != storedBinary->getSize())
- throw tcu::Exception("Binary size doesn't match");
-
- if (deMemCmp(binary->getBinary(), storedBinary->getBinary(), binary->getSize()))
- throw tcu::Exception("Binary contents don't match");
- }
-
- tcu::print(" OK: %s\n", progIter.getName().c_str());
- stats.numSucceeded += 1;
- }
- catch (const std::exception& e)
- {
- tcu::print(" ERROR: %s: %s\n", progIter.getName().c_str(), e.what());
-
- if (printLogs)
- {
- for (size_t shaderNdx = 0; shaderNdx < buildInfo.shaders.size(); shaderNdx++)
- {
- const glu::ShaderInfo& shaderInfo = buildInfo.shaders[shaderNdx];
- const char* const shaderName = getShaderTypeName(shaderInfo.type);
-
- tcu::print("%s source:\n---\n%s\n---\n", shaderName, shaderInfo.source.c_str());
- tcu::print("%s compile log:\n---\n%s\n---\n", shaderName, shaderInfo.infoLog.c_str());
- }
- }
-
- stats.numFailed += 1;
- }
+ buildProgram<vk::SpirVProgramInfo, vk::SpirVAsmCollection::Iterator>(casePath, printLogs, progIter, mode, &stats, reader.get(), writer.get());
}
}
// TestCase
-void TestCase::initPrograms (vk::ProgramCollection<glu::ProgramSources>&) const
+void TestCase::initPrograms (SourceCollections&) const
{
}
class ProgramBinary;
template<typename Program> class ProgramCollection;
class Allocator;
+struct SourceCollections;
}
namespace vkt
Context& operator= (const Context&); // Not allowed
};
+
class TestInstance;
class TestCase : public tcu::TestCase
TestCase (tcu::TestContext& testCtx, tcu::TestNodeType type, const std::string& name, const std::string& description);
virtual ~TestCase (void) {}
- virtual void initPrograms (vk::ProgramCollection<glu::ProgramSources>& programCollection) const;
+ virtual void initPrograms (vk::SourceCollections& programCollection) const;
virtual TestInstance* createInstance (Context& context) const = 0;
IterateResult iterate (void) { DE_ASSERT(false); return STOP; } // Deprecated in this module
template<typename Arg0>
struct NoPrograms1
{
- void init (vk::ProgramCollection<glu::ProgramSources>&, Arg0) const {}
+ void init (vk::SourceCollections&, Arg0) const {}
};
template<typename Instance, typename Arg0, typename Programs = NoPrograms1<Arg0> >
, m_arg0 (arg0)
{}
- void initPrograms (vk::ProgramCollection<glu::ProgramSources>& dst) const { m_progs.init(dst, m_arg0); }
+ void initPrograms (vk::SourceCollections& dst) const { m_progs.init(dst, m_arg0); }
TestInstance* createInstance (Context& context) const { return new Instance(context, m_arg0); }
private:
class FunctionPrograms0
{
public:
- typedef void (*Function) (vk::ProgramCollection<glu::ProgramSources>& dst);
+ typedef void (*Function) (vk::SourceCollections& dst);
FunctionPrograms0 (Function func)
: m_func(func)
{}
- void init (vk::ProgramCollection<glu::ProgramSources>& dst, FunctionInstance0::Function) const { m_func(dst); }
+ void init (vk::SourceCollections& dst, FunctionInstance0::Function) const { m_func(dst); }
private:
const Function m_func;
class FunctionPrograms1
{
public:
- typedef void (*Function) (vk::ProgramCollection<glu::ProgramSources>& dst, Arg0 arg0);
+ typedef void (*Function) (vk::SourceCollections& dst, Arg0 arg0);
FunctionPrograms1 (Function func)
: m_func(func)
{}
- void init (vk::ProgramCollection<glu::ProgramSources>& dst, const typename FunctionInstance1<Arg0>::Args& args) const { m_func(dst, args.arg0); }
+ void init (vk::SourceCollections& dst, const typename FunctionInstance1<Arg0>::Args& args) const { m_func(dst, args.arg0); }
private:
const Function m_func;
#include "vkPrograms.hpp"
#include "vkBinaryRegistry.hpp"
#include "vkGlslToSpirV.hpp"
+#include "vkSpirVAsm.hpp"
#include "deUniquePtr.hpp"
#include <vector>
#include <sstream>
+namespace // compilation
+{
+
+vk::ProgramBinary* compileProgram (const glu::ProgramSources& source, glu::ShaderProgramInfo* buildInfo)
+{
+ return vk::buildProgram(source, vk::PROGRAM_FORMAT_SPIRV, buildInfo);
+}
+
+vk::ProgramBinary* compileProgram (const vk::SpirVAsmSource& source, vk::SpirVProgramInfo* buildInfo)
+{
+ return vk::assembleProgram(source, buildInfo);
+}
+
+template <typename InfoType, typename IteratorType>
+vk::ProgramBinary* buildProgram (const std::string& casePath, IteratorType iter, vkt::Context* context, vk::BinaryCollection* progCollection)
+{
+ tcu::TestLog& log = context->getTestContext().getLog();
+ const vk::ProgramIdentifier progId (casePath, iter.getName());
+ const tcu::ScopedLogSection progSection (log, iter.getName(), "Program: " + iter.getName());
+ de::MovePtr<vk::ProgramBinary> binProg;
+ InfoType buildInfo;
+
+ try
+ {
+ binProg = de::MovePtr<vk::ProgramBinary>(compileProgram(iter.getProgram(), &buildInfo));
+ log << buildInfo;
+ }
+ catch (const tcu::NotSupportedError& err)
+ {
+ // Try to load from cache
+ const vk::BinaryRegistryReader registry (context->getTestContext().getArchive(), "vulkan/prebuilt");
+
+ log << err << tcu::TestLog::Message << "Building from source not supported, loading stored binary instead" << tcu::TestLog::EndMessage;
+
+ binProg = de::MovePtr<vk::ProgramBinary>(registry.loadProgram(progId));
+
+ log << iter.getProgram();
+ }
+ catch (const tcu::Exception&)
+ {
+ // Build failed for other reason
+ log << buildInfo;
+ throw;
+ }
+
+ TCU_CHECK_INTERNAL(binProg);
+
+ vk::ProgramBinary* returnBinary = binProg.get();
+
+ progCollection->add(progId.programName, binProg);
+
+ return returnBinary;
+}
+
+} // anonymous(compilation)
+
namespace vkt
{
{
const TestCase* vktCase = dynamic_cast<TestCase*>(testCase);
tcu::TestLog& log = m_context.getTestContext().getLog();
- vk::SourceCollection sourceProgs;
+ vk::SourceCollections sourceProgs;
DE_UNREF(casePath); // \todo [2015-03-13 pyry] Use this to identify ProgramCollection storage path
m_progCollection.clear();
vktCase->initPrograms(sourceProgs);
- for (vk::SourceCollection::Iterator progIter = sourceProgs.begin(); progIter != sourceProgs.end(); ++progIter)
+ for (vk::GlslSourceCollection::Iterator progIter = sourceProgs.glslSources.begin(); progIter != sourceProgs.glslSources.end(); ++progIter)
{
- const vk::ProgramIdentifier progId (casePath, progIter.getName());
- const tcu::ScopedLogSection progSection (log, progIter.getName(), "Program: " + progIter.getName());
- de::MovePtr<vk::ProgramBinary> binProg;
- glu::ShaderProgramInfo buildInfo;
-
- // \todo [2015-07-01 pyry] Command line parameter to control cache vs. build order?
-
- try
- {
- binProg = de::MovePtr<vk::ProgramBinary>(vk::buildProgram(progIter.getProgram(), vk::PROGRAM_FORMAT_SPIRV, &buildInfo));
- log << buildInfo;
- }
- catch (const tcu::NotSupportedError& err)
- {
- // Try to load from cache
- const vk::BinaryRegistryReader registry (m_context.getTestContext().getArchive(), "vulkan/prebuilt");
-
- log << err << TestLog::Message << "Building from source not supported, loading stored binary instead" << TestLog::EndMessage;
-
- binProg = de::MovePtr<vk::ProgramBinary>(registry.loadProgram(progId));
-
- log << progIter.getProgram();
- }
- catch (const tcu::Exception&)
- {
- // Build failed for other reason
- log << buildInfo;
- throw;
- }
-
- TCU_CHECK_INTERNAL(binProg);
+ vk::ProgramBinary* binProg = buildProgram<glu::ShaderProgramInfo, vk::GlslSourceCollection::Iterator>(casePath, progIter, &m_context, &m_progCollection);
try
{
{
log << err;
}
+ }
- m_progCollection.add(progId.programName, binProg);
+ for (vk::SpirVAsmCollection::Iterator asmIterator = sourceProgs.spirvAsmSources.begin(); asmIterator != sourceProgs.spirvAsmSources.end(); ++asmIterator)
+ {
+ buildProgram<vk::SpirVProgramInfo, vk::SpirVAsmCollection::Iterator>(casePath, asmIterator, &m_context, &m_progCollection);
}
DE_ASSERT(!m_instance);
endif ()
add_library(tcutil-platform STATIC ${TCUTIL_PLATFORM_SRCS})
+
+# Add vkutil to the deps before tcutil so that it picks up the c++11 dependencies
+target_link_libraries(tcutil-platform vkutil)
+
target_link_libraries(tcutil-platform tcutil ${TCUTIL_PLATFORM_LIBS})
# Always link to glutil as some platforms such as Win32 always support GL
target_link_libraries(tcutil-platform eglutil eglwrapper)
endif ()
-target_link_libraries(tcutil-platform vkutil)
-
# X11 libraries
if (DEQP_USE_X11)
find_package(X11 REQUIRED)