From cc38035841692780883f9cec274617108c57670c Mon Sep 17 00:00:00 2001 From: James Ross-Gowan Date: Tue, 16 Apr 2019 18:18:50 +1000 Subject: vo_gpu: d3d11: use the SPIRV-Cross C API directly When the D3D11 backend was first written, SPIRV-Cross only had a C++ API and no guarantee of API or ABI stability, so instead of using SPIRV-Cross directly, mpv used an unofficial C wrapper called crossc. Now that KhronosGroup/SPIRV-Cross#611 is resolved, SPIRV-Cross has an official C API that can be used instead, so remove crossc and use SPIRV-Cross directly. --- TOOLS/appveyor-build.sh | 2 +- TOOLS/appveyor-install.sh | 9 ++--- video/out/d3d11/ra_d3d11.c | 86 ++++++++++++++++++++++++++++++++++++---------- wscript | 8 ++--- 4 files changed, 77 insertions(+), 28 deletions(-) diff --git a/TOOLS/appveyor-build.sh b/TOOLS/appveyor-build.sh index 8796118df3..0c3aaacedd 100755 --- a/TOOLS/appveyor-build.sh +++ b/TOOLS/appveyor-build.sh @@ -11,7 +11,7 @@ export PYTHON=/usr/bin/python3 "$PYTHON" waf configure \ --check-c-compiler=gcc \ --disable-egl-angle-lib \ - --enable-crossc \ + --enable-spirv-cross \ --enable-d3d-hwaccel \ --enable-d3d11 \ --enable-egl-angle \ diff --git a/TOOLS/appveyor-install.sh b/TOOLS/appveyor-install.sh index 28e0674581..15595facf0 100755 --- a/TOOLS/appveyor-install.sh +++ b/TOOLS/appveyor-install.sh @@ -62,10 +62,11 @@ pacman -Sc --noconfirm ninja install ) -# Compile crossc +# Compile SPIRV-Cross ( - git clone --depth=1 https://github.com/rossy/crossc && cd crossc - git submodule update --init + git clone --depth=1 https://github.com/KhronosGroup/SPIRV-Cross && cd SPIRV-Cross - make -j4 install prefix=$MINGW_PREFIX + mkdir build && cd build + cmake -GNinja -DSPIRV_CROSS_SHARED=ON -DCMAKE_INSTALL_PREFIX=$MINGW_PREFIX .. + ninja install ) diff --git a/video/out/d3d11/ra_d3d11.c b/video/out/d3d11/ra_d3d11.c index 98c2d7d418..df9b3c0095 100644 --- a/video/out/d3d11/ra_d3d11.c +++ b/video/out/d3d11/ra_d3d11.c @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include "common/msg.h" #include "osdep/io.h" @@ -1255,19 +1255,23 @@ static bool compile_glsl(struct ra *ra, enum glsl_shader type, struct ra_d3d11 *p = ra->priv; struct spirv_compiler *spirv = p->spirv; void *ta_ctx = talloc_new(NULL); - crossc_compiler *cross = NULL; + spvc_result sc_res = SPVC_SUCCESS; + spvc_context sc_ctx = NULL; + spvc_parsed_ir sc_ir = NULL; + spvc_compiler sc_compiler = NULL; + spvc_compiler_options sc_opts = NULL; const char *hlsl = NULL; ID3DBlob *errors = NULL; bool success = false; HRESULT hr; - int cross_shader_model; + int sc_shader_model; if (p->fl >= D3D_FEATURE_LEVEL_11_0) { - cross_shader_model = 50; + sc_shader_model = 50; } else if (p->fl >= D3D_FEATURE_LEVEL_10_1) { - cross_shader_model = 41; + sc_shader_model = 41; } else { - cross_shader_model = 40; + sc_shader_model = 40; } int64_t start_us = mp_time_us(); @@ -1278,17 +1282,42 @@ static bool compile_glsl(struct ra *ra, enum glsl_shader type, int64_t shaderc_us = mp_time_us(); - cross = crossc_hlsl_create((uint32_t*)spv_module.start, - spv_module.len / sizeof(uint32_t)); + sc_res = spvc_context_create(&sc_ctx); + if (sc_res != SPVC_SUCCESS) + goto done; + + sc_res = spvc_context_parse_spirv(sc_ctx, (SpvId *)spv_module.start, + spv_module.len / sizeof(SpvId), &sc_ir); + if (sc_res != SPVC_SUCCESS) + goto done; - crossc_hlsl_set_shader_model(cross, cross_shader_model); - crossc_set_flip_vert_y(cross, type == GLSL_SHADER_VERTEX); + sc_res = spvc_context_create_compiler(sc_ctx, SPVC_BACKEND_HLSL, sc_ir, + SPVC_CAPTURE_MODE_TAKE_OWNERSHIP, + &sc_compiler); + if (sc_res != SPVC_SUCCESS) + goto done; - hlsl = crossc_compile(cross); - if (!hlsl) { - MP_ERR(ra, "SPIRV-Cross failed: %s\n", crossc_strerror(cross)); + sc_res = spvc_compiler_create_compiler_options(sc_compiler, &sc_opts); + if (sc_res != SPVC_SUCCESS) goto done; + sc_res = spvc_compiler_options_set_uint(sc_opts, + SPVC_COMPILER_OPTION_HLSL_SHADER_MODEL, sc_shader_model); + if (sc_res != SPVC_SUCCESS) + goto done; + if (type == GLSL_SHADER_VERTEX) { + // FLIP_VERTEX_Y is only valid for vertex shaders + sc_res = spvc_compiler_options_set_bool(sc_opts, + SPVC_COMPILER_OPTION_FLIP_VERTEX_Y, SPVC_TRUE); + if (sc_res != SPVC_SUCCESS) + goto done; } + sc_res = spvc_compiler_install_compiler_options(sc_compiler, sc_opts); + if (sc_res != SPVC_SUCCESS) + goto done; + + sc_res = spvc_compiler_compile(sc_compiler, &hlsl); + if (sc_res != SPVC_SUCCESS) + goto done; int64_t cross_us = mp_time_us(); @@ -1312,7 +1341,11 @@ static bool compile_glsl(struct ra *ra, enum glsl_shader type, d3dcompile_us - cross_us); success = true; -done:; +done: + if (sc_res != SPVC_SUCCESS) { + MP_MSG(ra, MSGL_ERR, "SPIRV-Cross failed: %s\n", + spvc_context_get_last_error_string(sc_ctx)); + } int level = success ? MSGL_DEBUG : MSGL_ERR; MP_MSG(ra, level, "GLSL source:\n"); mp_log_source(ra->log, level, glsl); @@ -1321,7 +1354,8 @@ done:; mp_log_source(ra->log, level, hlsl); } SAFE_RELEASE(errors); - crossc_destroy(cross); + if (sc_ctx) + spvc_context_destroy(sc_ctx); talloc_free(ta_ctx); return success; } @@ -1418,14 +1452,16 @@ static size_t vbuf_upload(struct ra *ra, void *data, size_t size) } static const char cache_magic[4] = "RD11"; -static const int cache_version = 2; +static const int cache_version = 3; struct cache_header { char magic[sizeof(cache_magic)]; int cache_version; char compiler[SPIRV_NAME_MAX_LEN]; int spv_compiler_version; - uint32_t cross_version; + unsigned spvc_compiler_major; + unsigned spvc_compiler_minor; + unsigned spvc_compiler_patch; struct dll_version d3d_compiler_version; int feature_level; size_t vert_bytecode_len; @@ -1449,6 +1485,9 @@ static void load_cached_program(struct ra *ra, struct cache_header *header = (struct cache_header *)cache.start; cache = bstr_cut(cache, sizeof(*header)); + unsigned spvc_major, spvc_minor, spvc_patch; + spvc_get_version(&spvc_major, &spvc_minor, &spvc_patch); + if (strncmp(header->magic, cache_magic, sizeof(cache_magic)) != 0) return; if (header->cache_version != cache_version) @@ -1457,7 +1496,11 @@ static void load_cached_program(struct ra *ra, return; if (header->spv_compiler_version != spirv->compiler_version) return; - if (header->cross_version != crossc_version()) + if (header->spvc_compiler_major != spvc_major) + return; + if (header->spvc_compiler_minor != spvc_minor) + return; + if (header->spvc_compiler_patch != spvc_patch) return; if (!dll_version_equal(header->d3d_compiler_version, p->d3d_compiler_ver)) return; @@ -1491,10 +1534,15 @@ static void save_cached_program(struct ra *ra, struct ra_renderpass *pass, struct ra_d3d11 *p = ra->priv; struct spirv_compiler *spirv = p->spirv; + unsigned spvc_major, spvc_minor, spvc_patch; + spvc_get_version(&spvc_major, &spvc_minor, &spvc_patch); + struct cache_header header = { .cache_version = cache_version, .spv_compiler_version = p->spirv->compiler_version, - .cross_version = crossc_version(), + .spvc_compiler_major = spvc_major, + .spvc_compiler_minor = spvc_minor, + .spvc_compiler_patch = spvc_patch, .d3d_compiler_version = p->d3d_compiler_ver, .feature_level = p->fl, .vert_bytecode_len = vert_bc.len, diff --git a/wscript b/wscript index 29cc0ef4e8..453eb0d742 100644 --- a/wscript +++ b/wscript @@ -747,13 +747,13 @@ video_output_features = [ 'deps': 'shaderc-shared || shaderc-static', 'func': check_true, }, { - 'name': '--crossc', - 'desc': 'libcrossc SPIR-V translator', - 'func': check_pkg_config('crossc'), + 'name': '--spirv-cross', + 'desc': 'SPIRV-Cross SPIR-V shader converter', + 'func': check_pkg_config('spirv-cross-c-shared'), }, { 'name': '--d3d11', 'desc': 'Direct3D 11 video output', - 'deps': 'win32-desktop && shaderc && crossc', + 'deps': 'win32-desktop && shaderc && spirv-cross', 'func': check_cc(header_name=['d3d11_1.h', 'dxgi1_2.h']), }, { # We need MMAL/bcm_host/dispmanx APIs. Also, most RPI distros require -- cgit v1.2.3