Skip to content
Snippets Groups Projects
spirv.c 383 KiB
Newer Older
/*
 * Copyright 2017 Józef Kucia for CodeWeavers
 * Copyright 2021 Conor McCarthy for Codeweavers
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include "vkd3d_shader_private.h"

#ifdef HAVE_SPIRV_UNIFIED1_SPIRV_H
# include "spirv/unified1/spirv.h"
#else
# include "vulkan/spirv.h"
#endif  /* HAVE_SPIRV_UNIFIED1_SPIRV_H */
#ifdef HAVE_SPIRV_UNIFIED1_GLSL_STD_450_H
# include "spirv/unified1/GLSL.std.450.h"
#else
# include "vulkan/GLSL.std.450.h"
#endif  /* HAVE_SPIRV_UNIFIED1_GLSL_STD_450_H */
# include "spirv-tools/libspirv.h"
static spv_target_env spv_target_env_from_vkd3d(enum vkd3d_shader_spirv_environment environment)
            return SPV_ENV_OPENGL_4_5;
            return SPV_ENV_VULKAN_1_0;
        default:
static uint32_t get_binary_to_text_options(enum vkd3d_shader_compile_option_formatting_flags formatting)
{
    uint32_t out = 0;
    unsigned int i;

    static const struct
    {
        enum vkd3d_shader_compile_option_formatting_flags vkd3d;
        uint32_t spv;
        {VKD3D_SHADER_COMPILE_OPTION_FORMATTING_COLOUR,     SPV_BINARY_TO_TEXT_OPTION_COLOR           },
        {VKD3D_SHADER_COMPILE_OPTION_FORMATTING_INDENT,     SPV_BINARY_TO_TEXT_OPTION_INDENT          },
        {VKD3D_SHADER_COMPILE_OPTION_FORMATTING_OFFSETS,    SPV_BINARY_TO_TEXT_OPTION_SHOW_BYTE_OFFSET},
        {VKD3D_SHADER_COMPILE_OPTION_FORMATTING_HEADER,     SPV_BINARY_TO_TEXT_OPTION_NO_HEADER,        true},
        {VKD3D_SHADER_COMPILE_OPTION_FORMATTING_RAW_IDS,    SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES,   true},
    for (i = 0; i < ARRAY_SIZE(valuemap); ++i)
    {
        if (valuemap[i].invert == !(formatting & valuemap[i].vkd3d))
static enum vkd3d_result vkd3d_spirv_binary_to_text(const struct vkd3d_shader_code *spirv,
        enum vkd3d_shader_spirv_environment environment, uint32_t options, struct vkd3d_shader_code *out)
{
    spv_diagnostic diagnostic = NULL;
    spv_text text = NULL;
    spv_context context;
    spv_result_t spvret;
    enum vkd3d_result result = VKD3D_OK;
    context = spvContextCreate(spv_target_env_from_vkd3d(environment));
    if (!(spvret = spvBinaryToText(context, spirv->code, spirv->size / sizeof(uint32_t),
        void *code = vkd3d_malloc(text->length);
        if (code)
            memcpy(code, text->str, text->length);
            out->size = text->length;
            out->code = code;
        else
            result = VKD3D_ERROR_OUT_OF_MEMORY;
        FIXME("Failed to convert SPIR-V binary to text, ret %d.\n", spvret);
        FIXME("Diagnostic message: %s.\n", debugstr_a(diagnostic->error));
    }

    spvTextDestroy(text);
    spvDiagnosticDestroy(diagnostic);
    spvContextDestroy(context);

    return result;
}

static void vkd3d_spirv_dump(const struct vkd3d_shader_code *spirv,
        enum vkd3d_shader_spirv_environment environment)
{
    const static uint32_t options
        = SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES | SPV_BINARY_TO_TEXT_OPTION_INDENT;
    struct vkd3d_shader_code text;

    if (!vkd3d_spirv_binary_to_text(spirv, environment, options, &text))
    {
        const char *str, *current = text.code;
        while ((str = strchr(current, '\n')))
        {
            TRACE("%.*s\n", (int)(str - current), current);
            current = str + 1;
        }

        vkd3d_shader_free_shader_code(&text);
    }
static void vkd3d_spirv_validate(const struct vkd3d_shader_code *spirv,
        enum vkd3d_shader_spirv_environment environment)
{
    spv_diagnostic diagnostic = NULL;
    spv_context context;
    spv_result_t ret;

    context = spvContextCreate(spv_target_env_from_vkd3d(environment));

    if ((ret = spvValidateBinary(context, spirv->code, spirv->size / sizeof(uint32_t),
            &diagnostic)))
    {
        FIXME("Failed to validate SPIR-V binary, ret %d.\n", ret);
        FIXME("Diagnostic message: %s.\n", debugstr_a(diagnostic->error));
static uint32_t get_binary_to_text_options(enum vkd3d_shader_compile_option_formatting_flags formatting)
{
    return 0;
}
static enum vkd3d_result vkd3d_spirv_binary_to_text(const struct vkd3d_shader_code *spirv,
        enum vkd3d_shader_spirv_environment environment, uint32_t options, struct vkd3d_shader_code *out)
{
    return VKD3D_ERROR;
}
static void vkd3d_spirv_dump(const struct vkd3d_shader_code *spirv,
        enum vkd3d_shader_spirv_environment environment) {}
static void vkd3d_spirv_validate(const struct vkd3d_shader_code *spirv,
        enum vkd3d_shader_spirv_environment environment) {}
#endif  /* HAVE_SPIRV_TOOLS */
static enum vkd3d_shader_input_sysval_semantic vkd3d_siv_from_sysval_indexed(enum vkd3d_shader_sysval_semantic sysval,
            return VKD3D_SIV_POSITION;
            return VKD3D_SIV_QUAD_U0_TESS_FACTOR + index;
            return VKD3D_SIV_QUAD_U_INNER_TESS_FACTOR + index;
            return VKD3D_SIV_TRIANGLE_U_TESS_FACTOR + index;
            return VKD3D_SIV_TRIANGLE_INNER_TESS_FACTOR;
Loading
Loading full blame...