From 786a31ca4e4b88658a1827492c34992576c5b210 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3zef=20Kucia?= Date: Mon, 19 Jun 2017 18:05:53 +0200 Subject: [PATCH] libs/vkd3d-shader: Use libSPIRV-Tools for tracing and validating generated SPIR-V shaders. SPIRV-Tools are an optional dependency. We link with stdc++ because libSPIRV-Tools is a static library written in C++. --- Makefile.am | 2 +- configure.ac | 20 +++++++++++++ libs/vkd3d-shader/spirv.c | 60 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 88255a8a..3f12af50 100644 --- a/Makefile.am +++ b/Makefile.am @@ -69,7 +69,7 @@ libvkd3d_shader_la_SOURCES = \ libs/vkd3d-shader/spirv.c \ libs/vkd3d-shader/vkd3d_shader_main.c \ libs/vkd3d-shader/vkd3d_shader_private.h -libvkd3d_shader_la_LIBADD = libvkd3d-common.la +libvkd3d_shader_la_LIBADD = libvkd3d-common.la @SPIRV_TOOLS_LIBS@ libvkd3d_la_SOURCES = \ include/d3d12.idl \ diff --git a/configure.ac b/configure.ac index 826fa2a4..01ac07b5 100644 --- a/configure.ac +++ b/configure.ac @@ -10,6 +10,8 @@ AC_ARG_VAR([WIDL], [widl IDL compiler]) AC_ARG_VAR([GLSLANG], [glslangValidator GLSL compiler]) AC_ARG_VAR([CROSSCC32], [32-bit Windows cross compiler]) AC_ARG_VAR([CROSSCC64], [64-bit Windows cross compiler]) +AC_ARG_WITH([spirv-tools], AS_HELP_STRING([--with-spirv-tools], + [Build with SPIRV-Tools library (default: disabled)])) dnl Check for progs AM_PROG_AR @@ -62,9 +64,14 @@ AS_IF([test "x$ac_cv_header_vulkan_vulkan_h" != "xyes"], [AC_MSG_ERROR([vulkan.h AS_IF([test "x$ac_cv_header_spirv_1_0_spirv_h" != "xyes"], [AC_MSG_ERROR([spirv.h not found.])]) AS_IF([test "x$ac_cv_header_spirv_1_0_GLSL_std_450_h" != "xyes"], [AC_MSG_ERROR([GLSL.std.450.h not found.])]) +AS_IF([test "x$with_spirv_tools" = "xyes"], + [AC_CHECK_HEADERS([spirv-tools/libspirv.h], [], [AC_MSG_ERROR([spirv-tools/libspirv.h not found.])])]) + dnl Check for libraries m4_ifdef([PKG_PROG_PKG_CONFIG], [PKG_PROG_PKG_CONFIG], [m4_fatal([pkg-config autoconf macros not found.])]) +AC_CHECK_LIB([m], [ceilf]) + AC_ARG_VAR([PTHREAD_LIBS], [linker flags for pthreads]) AC_CHECK_LIB([pthread], [pthread_create], [AC_SUBST([PTHREAD_LIBS], ["-lpthread"])], @@ -75,6 +82,12 @@ AC_CHECK_LIB([vulkan], [vkGetInstanceProcAddr], [VULKAN_LIBS="-lvulkan"], [AC_MSG_ERROR([libvulkan not found.])]) +AC_SUBST([SPIRV_TOOLS_LIBS]) +AS_IF([test "x$with_spirv_tools" = "xyes"], + [AC_CHECK_LIB([SPIRV-Tools], [spvTextToBinary], + [SPIRV_TOOLS_LIBS="-lstdc++ -lSPIRV-Tools"], + [AC_MSG_ERROR([libSPIRV-Tools not found.])], [-lstdc++])]) + PKG_CHECK_MODULES([XCB], [xcb xcb-keysyms]) dnl Check for functions @@ -84,6 +97,11 @@ VKD3D_CHECK_SYNC_SUB_AND_FETCH_FUNC AM_CONDITIONAL([HAS_CROSSTARGET32], [test "x$CROSSTARGET32" != "xno"]) AM_CONDITIONAL([HAS_CROSSTARGET64], [test "x$CROSSTARGET64" != "xno"]) +AS_IF([test "x$ac_cv_header_spirv_tools_libspirv_h" = "xyes" -a "x$ac_cv_lib_SPIRV_Tools_spvTextToBinary" = "xyes"], + [AC_DEFINE([HAVE_SPIRV_TOOLS], [1], [Define to 1 if you have SPIRV-Tools.]) + HAVE_SPIRV_TOOLS=yes], + [HAVE_SPIRV_TOOLS=no]) + AC_CONFIG_FILES([Makefile]) AC_OUTPUT @@ -94,6 +112,8 @@ AS_IF([test "x$CROSSTARGET32" != "xno" -o "x$CROSSTARGET64" != "xno"], AS_ECHO([" Configuration summary for $PACKAGE $VERSION + Have SPIRV-Tools: ${HAVE_SPIRV_TOOLS} + Building crosstests: ${HAVE_CROSSTEST}"]) AS_IF([test "x$CROSSTARGET32" != "xno"], [AS_ECHO([" Using 32-bit cross compiler: $CROSSCC32"])]) AS_IF([test "x$CROSSTARGET64" != "xno"], [AS_ECHO([" Using 64-bit cross compiler: $CROSSCC64"])]) diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 8c1c61bc..1b2a06c9 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -19,10 +19,70 @@ #include "vkd3d_shader_private.h" #include "spirv/1.0/spirv.h" +#ifdef HAVE_SPIRV_TOOLS +# include "spirv-tools/libspirv.h" +#endif /* HAVE_SPIRV_TOOLS */ + +#ifdef HAVE_SPIRV_TOOLS + +static void vkd3d_spirv_dump(const struct vkd3d_shader_code *spirv) +{ + const static uint32_t options + = SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES | SPV_BINARY_TO_TEXT_OPTION_INDENT; + spv_diagnostic diagnostic = NULL; + spv_text text = NULL; + spv_context context; + spv_result_t ret; + + context = spvContextCreate(SPV_ENV_VULKAN_1_0); + + if (!(ret = spvBinaryToText(context, spirv->code, spirv->size / sizeof(uint32_t), + options, &text, &diagnostic))) + { + const char *str, *current = text->str; + while ((str = strchr(current, '\n'))) + { + TRACE("%.*s\n", (int)(str - current), current); + current = str + 1; + } + } + else + { + TRACE("Failed to convert SPIR-V to binary text, ret %d.\n", ret); + TRACE("Diagnostic message: %s.\n", debugstr_a(diagnostic->error)); + } + + spvTextDestroy(text); + spvDiagnosticDestroy(diagnostic); + spvContextDestroy(context); +} + +static void vkd3d_spirv_validate(const struct vkd3d_shader_code *spirv) +{ + spv_diagnostic diagnostic = NULL; + spv_context context; + spv_result_t ret; + + context = spvContextCreate(SPV_ENV_VULKAN_1_0); + + if ((ret = spvValidateBinary(context, spirv->code, spirv->size / sizeof(uint32_t), + &diagnostic))) + { + TRACE("Failed to validate SPIR-V binary, ret %d.\n", ret); + TRACE("Diagnostic message: %s.\n", debugstr_a(diagnostic->error)); + } + + spvDiagnosticDestroy(diagnostic); + spvContextDestroy(context); +} + +#else static void vkd3d_spirv_dump(const struct vkd3d_shader_code *spirv) {} static void vkd3d_spirv_validate(const struct vkd3d_shader_code *spirv) {} +#endif /* HAVE_SPIRV_TOOLS */ + struct vkd3d_spirv_stream { uint32_t *words;