Skip to content
Snippets Groups Projects
spirv.c 364 KiB
Newer Older
/*
 * Copyright 2017 Józef Kucia 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 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 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;
            return VKD3D_SIV_LINE_DETAIL_TESS_FACTOR;
            return VKD3D_SIV_LINE_DENSITY_TESS_FACTOR;
            FIXME("Unhandled sysval %#x, index %u.\n", sysval, index);
static enum vkd3d_shader_input_sysval_semantic vkd3d_siv_from_sysval(enum vkd3d_shader_sysval_semantic sysval)
{
      return vkd3d_siv_from_sysval_indexed(sysval, 0);
}

#define VKD3D_SPIRV_VERSION 0x00010000
#define VKD3D_SPIRV_GENERATOR_ID 18
#define VKD3D_SPIRV_GENERATOR_VERSION 1
#define VKD3D_SPIRV_GENERATOR_MAGIC ((VKD3D_SPIRV_GENERATOR_ID << 16) | VKD3D_SPIRV_GENERATOR_VERSION)

struct vkd3d_spirv_stream
{
    uint32_t *words;
    size_t capacity;
    size_t word_count;
};

static void vkd3d_spirv_stream_init(struct vkd3d_spirv_stream *stream)
{
    stream->capacity = 256;
    if (!(stream->words = vkd3d_calloc(stream->capacity, sizeof(*stream->words))))
        stream->capacity = 0;
    stream->word_count = 0;

    list_init(&stream->inserted_chunks);
}

struct vkd3d_spirv_chunk
Loading
Loading full blame...