Skip to content
Snippets Groups Projects
spirv.c 400 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,
        enum vkd3d_shader_compile_option_formatting_flags formatting, 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),
            get_binary_to_text_options(formatting), &text, &diagnostic)))
        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)
{
    static const enum vkd3d_shader_compile_option_formatting_flags formatting
            = VKD3D_SHADER_COMPILE_OPTION_FORMATTING_INDENT | VKD3D_SHADER_COMPILE_OPTION_FORMATTING_HEADER;
    if (!vkd3d_spirv_binary_to_text(spirv, environment, formatting, &text))
        vkd3d_shader_trace_text(text.code, text.size);
        vkd3d_shader_free_shader_code(&text);
    }
static bool vkd3d_spirv_validate(struct vkd3d_string_buffer *buffer, 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)))
    {
        vkd3d_string_buffer_printf(buffer, "%s", diagnostic->error);
    }

    spvDiagnosticDestroy(diagnostic);
    spvContextDestroy(context);
static enum vkd3d_result vkd3d_spirv_binary_to_text(const struct vkd3d_shader_code *spirv,
        enum vkd3d_shader_spirv_environment environment,
        enum vkd3d_shader_compile_option_formatting_flags formatting, struct vkd3d_shader_code *out)
static void vkd3d_spirv_dump(const struct vkd3d_shader_code *spirv,
        enum vkd3d_shader_spirv_environment environment) {}
static bool vkd3d_spirv_validate(struct vkd3d_string_buffer *buffer, const struct vkd3d_shader_code *spirv,
        enum vkd3d_shader_spirv_environment environment)
{
    return true;
}
#endif  /* HAVE_SPIRV_TOOLS */
enum vkd3d_shader_input_sysval_semantic vkd3d_siv_from_sysval_indexed(enum vkd3d_shader_sysval_semantic sysval,
        case VKD3D_SHADER_SV_COVERAGE:
        case VKD3D_SHADER_SV_DEPTH:
        case VKD3D_SHADER_SV_DEPTH_GREATER_EQUAL:
        case VKD3D_SHADER_SV_DEPTH_LESS_EQUAL:
        case VKD3D_SHADER_SV_STENCIL_REF:
        case VKD3D_SHADER_SV_TARGET:
            return VKD3D_SIV_POSITION;
        case VKD3D_SHADER_SV_INSTANCE_ID:
            return VKD3D_SIV_INSTANCE_ID;
        case VKD3D_SHADER_SV_IS_FRONT_FACE:
            return VKD3D_SIV_IS_FRONT_FACE;
        case VKD3D_SHADER_SV_PRIMITIVE_ID:
            return VKD3D_SIV_PRIMITIVE_ID;
        case VKD3D_SHADER_SV_RENDER_TARGET_ARRAY_INDEX:
Loading
Loading full blame...