[PATCH vkd3d 13/41] vkd3d-shader: Add integration for DXIL shaders.

Hans-Kristian Arntzen post at arntzen-software.no
Wed Jan 29 05:51:42 CST 2020


If we detect that a blob contains a DXIL chunk, use dxil-spirv to
compile the shader to SPIR-V if it is enabled in the build.

Signed-off-by: Hans-Kristian Arntzen <post at arntzen-software.no>
---
 Makefile.am                              |   4 +
 libs/vkd3d-shader/dxil.c                 | 439 +++++++++++++++++++++++
 libs/vkd3d-shader/vkd3d_shader_main.c    |  53 ++-
 libs/vkd3d-shader/vkd3d_shader_private.h |   8 +
 4 files changed, 489 insertions(+), 15 deletions(-)
 create mode 100644 libs/vkd3d-shader/dxil.c

diff --git a/Makefile.am b/Makefile.am
index 1e2959f..2ceb5a8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -90,6 +90,10 @@ if HAVE_LD_VERSION_SCRIPT
 libvkd3d_shader_la_LDFLAGS += -Wl,--version-script=$(srcdir)/libs/vkd3d-shader/vkd3d_shader.map
 EXTRA_libvkd3d_shader_la_DEPENDENCIES = $(srcdir)/libs/vkd3d-shader/vkd3d_shader.map
 endif
+if HAVE_DXIL_SPV
+libvkd3d_shader_la_SOURCES += \
+	libs/vkd3d-shader/dxil.c
+endif
 
 libvkd3d_la_SOURCES = \
 	include/private/vkd3d_common.h \
diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c
new file mode 100644
index 0000000..f3fb5a3
--- /dev/null
+++ b/libs/vkd3d-shader/dxil.c
@@ -0,0 +1,439 @@
+/*
+ * Copyright 2020 Hans-Kristian Arntzen for Valve Corporation
+ *
+ * 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"
+#include <dxil_spirv_c.h>
+
+static bool dxil_match_shader_visibility(enum vkd3d_shader_visibility visibility,
+                                         dxil_spv_shader_stage stage)
+{
+    if (visibility == VKD3D_SHADER_VISIBILITY_ALL)
+        return true;
+
+    switch (stage)
+    {
+        case DXIL_SPV_STAGE_VERTEX:
+            return visibility == VKD3D_SHADER_VISIBILITY_VERTEX;
+        case DXIL_SPV_STAGE_HULL:
+            return visibility == VKD3D_SHADER_VISIBILITY_HULL;
+        case DXIL_SPV_STAGE_DOMAIN:
+            return visibility == VKD3D_SHADER_VISIBILITY_DOMAIN;
+        case DXIL_SPV_STAGE_GEOMETRY:
+            return visibility == VKD3D_SHADER_VISIBILITY_GEOMETRY;
+        case DXIL_SPV_STAGE_PIXEL:
+            return visibility == VKD3D_SHADER_VISIBILITY_PIXEL;
+        case DXIL_SPV_STAGE_COMPUTE:
+            return visibility == VKD3D_SHADER_VISIBILITY_COMPUTE;
+        default:
+            return false;
+    }
+}
+
+static unsigned dxil_resource_flags_from_kind(dxil_spv_resource_kind kind)
+{
+    switch (kind)
+    {
+        case DXIL_SPV_RESOURCE_KIND_RAW_BUFFER:
+        case DXIL_SPV_RESOURCE_KIND_TYPED_BUFFER:
+        case DXIL_SPV_RESOURCE_KIND_STRUCTURED_BUFFER:
+            return VKD3D_SHADER_BINDING_FLAG_BUFFER;
+
+        default:
+            return VKD3D_SHADER_BINDING_FLAG_IMAGE;
+    }
+}
+
+static dxil_spv_bool dxil_srv_remap(void *userdata, const dxil_spv_d3d_binding *d3d_binding,
+                                    dxil_spv_vulkan_binding *vk_binding)
+{
+    const struct vkd3d_shader_interface_info *shader_interface_info = userdata;
+    unsigned int binding_count = shader_interface_info->binding_count;
+    unsigned int i, resource_flags;
+    resource_flags = dxil_resource_flags_from_kind(d3d_binding->kind);
+
+    for (i = 0; i < binding_count; i++)
+    {
+        const struct vkd3d_shader_resource_binding *binding = &shader_interface_info->bindings[i];
+        if (binding->type == VKD3D_SHADER_DESCRIPTOR_TYPE_SRV &&
+            binding->register_space == d3d_binding->register_space &&
+            binding->register_index == d3d_binding->register_index &&
+            (binding->flags & resource_flags) != 0 &&
+            dxil_match_shader_visibility(binding->shader_visibility, d3d_binding->stage))
+        {
+            memset(vk_binding, 0, sizeof(*vk_binding));
+            vk_binding->set = binding->binding.set;
+            vk_binding->binding = binding->binding.binding;
+            return DXIL_SPV_TRUE;
+        }
+    }
+
+    return DXIL_SPV_FALSE;
+}
+
+static dxil_spv_bool dxil_sampler_remap(void *userdata, const dxil_spv_d3d_binding *d3d_binding,
+                                        dxil_spv_vulkan_binding *vk_binding)
+{
+    const struct vkd3d_shader_interface_info *shader_interface_info = userdata;
+    unsigned int binding_count = shader_interface_info->binding_count;
+    unsigned int i;
+
+    for (i = 0; i < binding_count; i++)
+    {
+        const struct vkd3d_shader_resource_binding *binding = &shader_interface_info->bindings[i];
+        if (binding->type == VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER &&
+            binding->register_space == d3d_binding->register_space &&
+            binding->register_index == d3d_binding->register_index &&
+            dxil_match_shader_visibility(binding->shader_visibility, d3d_binding->stage))
+        {
+            memset(vk_binding, 0, sizeof(*vk_binding));
+            vk_binding->set = binding->binding.set;
+            vk_binding->binding = binding->binding.binding;
+            return DXIL_SPV_TRUE;
+        }
+    }
+
+    return DXIL_SPV_FALSE;
+}
+
+static dxil_spv_bool dxil_input_remap(void *userdata, const dxil_spv_d3d_vertex_input *d3d_input,
+                                      dxil_spv_vulkan_vertex_input *vk_input)
+{
+    vk_input->location = d3d_input->start_row;
+    return DXIL_SPV_TRUE;
+}
+
+static dxil_spv_bool dxil_output_remap(void *userdata, const dxil_spv_d3d_stream_output *d3d_output,
+                                       dxil_spv_vulkan_stream_output *vk_output)
+{
+    const struct vkd3d_shader_transform_feedback_info *xfb_info = userdata;
+    const struct vkd3d_shader_transform_feedback_element *xfb_element;
+    unsigned int i, offset, stride;
+
+    offset = 0;
+    xfb_element = NULL;
+
+    for (i = 0; i < xfb_info->element_count; ++i)
+    {
+        const struct vkd3d_shader_transform_feedback_element *e = &xfb_info->elements[i];
+
+        /* TODO: Stream index matching? */
+        if (!ascii_strcasecmp(e->semantic_name, d3d_output->semantic) && e->semantic_index == d3d_output->semantic_index)
+        {
+            xfb_element = e;
+            break;
+        }
+
+        offset += 4 * e->component_count;
+    }
+
+    if (!xfb_element)
+    {
+        vk_output->enable = DXIL_SPV_FALSE;
+        return DXIL_SPV_TRUE;
+    }
+
+    if (xfb_element->output_slot < xfb_info->buffer_stride_count)
+    {
+        stride = xfb_info->buffer_strides[xfb_element->output_slot];
+    }
+    else
+    {
+        stride = 0;
+        for (i = 0; i < xfb_info->element_count; ++i)
+        {
+            const struct vkd3d_shader_transform_feedback_element *e = &xfb_info->elements[i];
+
+            if (e->stream_index == xfb_element->stream_index && e->output_slot == xfb_element->output_slot)
+                stride += 4 * e->component_count;
+        }
+    }
+
+    vk_output->enable = DXIL_SPV_TRUE;
+    vk_output->offset = offset;
+    vk_output->stride = stride;
+    vk_output->buffer_index = xfb_element->output_slot;
+    return DXIL_SPV_TRUE;
+}
+
+static dxil_spv_bool dxil_uav_remap(void *userdata, const dxil_spv_uav_d3d_binding *d3d_binding,
+                                    dxil_spv_uav_vulkan_binding *vk_binding)
+{
+    const struct vkd3d_shader_interface_info *shader_interface_info = userdata;
+    const struct vkd3d_shader_effective_uav_counter_binding_info *counter_info;
+    unsigned int binding_count = shader_interface_info->binding_count;
+    unsigned int i, j, resource_flags;
+
+    resource_flags = dxil_resource_flags_from_kind(d3d_binding->d3d_binding.kind);
+
+    for (i = 0; i < binding_count; i++)
+    {
+        const struct vkd3d_shader_resource_binding *binding = &shader_interface_info->bindings[i];
+        if (binding->type == VKD3D_SHADER_DESCRIPTOR_TYPE_UAV &&
+            binding->register_space == d3d_binding->d3d_binding.register_space &&
+            binding->register_index == d3d_binding->d3d_binding.register_index &&
+            (binding->flags & resource_flags) != 0 &&
+            dxil_match_shader_visibility(binding->shader_visibility, d3d_binding->d3d_binding.stage))
+        {
+            memset(vk_binding, 0, sizeof(*vk_binding));
+            vk_binding->buffer_binding.set = binding->binding.set;
+            vk_binding->buffer_binding.binding = binding->binding.binding;
+
+            if (d3d_binding->has_counter)
+            {
+                unsigned int resource_index = d3d_binding->d3d_binding.resource_index;
+                for (j = 0; j < shader_interface_info->uav_counter_count; j++)
+                {
+                    /* Match UAV counters by resource index, and not binding. */
+                    if (shader_interface_info->uav_counters[j].counter_index == resource_index)
+                    {
+                        counter_info = vkd3d_find_struct(shader_interface_info->next, EFFECTIVE_UAV_COUNTER_BINDING_INFO);
+
+                        if (counter_info && resource_index < counter_info->uav_counter_count)
+                        {
+                            /* Let pipeline know what the actual space/bindings for the counter are. */
+                            counter_info->uav_register_bindings[resource_index] = d3d_binding->d3d_binding.register_index;
+                            counter_info->uav_register_spaces[resource_index] = d3d_binding->d3d_binding.register_space;
+                        }
+
+                        vk_binding->counter_binding.set = shader_interface_info->uav_counters[j].binding.set;
+                        vk_binding->counter_binding.binding = shader_interface_info->uav_counters[j].binding.binding;
+                        break;
+                    }
+                }
+
+                if (j == shader_interface_info->uav_counter_count)
+                    return DXIL_SPV_FALSE;
+            }
+
+            return DXIL_SPV_TRUE;
+        }
+    }
+
+    return DXIL_SPV_FALSE;
+}
+
+static dxil_spv_bool dxil_cbv_remap(void *userdata, const dxil_spv_d3d_binding *d3d_binding,
+                                    dxil_spv_cbv_vulkan_binding *vk_binding)
+{
+    const struct vkd3d_shader_interface_info *shader_interface_info = userdata;
+    unsigned int binding_count = shader_interface_info->binding_count;
+    unsigned int i;
+
+    /* Try to map to root constant -> push constant.
+     * Do not consider shader visibility here, as DXBC path does not appear to do it either. */
+    for (i = 0; i < shader_interface_info->push_constant_buffer_count; i++)
+    {
+        const struct vkd3d_shader_push_constant_buffer *push = &shader_interface_info->push_constant_buffers[i];
+        if (push->register_space == d3d_binding->register_space &&
+            push->register_index == d3d_binding->register_index)
+        {
+            memset(vk_binding, 0, sizeof(*vk_binding));
+            vk_binding->push_constant = DXIL_SPV_TRUE;
+            vk_binding->vulkan.push_constant.offset_in_words = push->offset / sizeof(uint32_t);
+            return DXIL_SPV_TRUE;
+        }
+    }
+
+    /* Fall back to regular CBV -> UBO. */
+    for (i = 0; i < binding_count; i++)
+    {
+        const struct vkd3d_shader_resource_binding *binding = &shader_interface_info->bindings[i];
+        if (binding->type == VKD3D_SHADER_DESCRIPTOR_TYPE_CBV &&
+            binding->register_space == d3d_binding->register_space &&
+            binding->register_index == d3d_binding->register_index &&
+            dxil_match_shader_visibility(binding->shader_visibility, d3d_binding->stage))
+        {
+            memset(vk_binding, 0, sizeof(*vk_binding));
+            vk_binding->vulkan.uniform_binding.set = binding->binding.set;
+            vk_binding->vulkan.uniform_binding.binding = binding->binding.binding;
+            return DXIL_SPV_TRUE;
+        }
+    }
+
+    return DXIL_SPV_FALSE;
+}
+
+static dxil_spv_bool dxil_uav_scan(
+        void *userdata,
+        const dxil_spv_uav_d3d_binding *binding,
+        dxil_spv_uav_vulkan_binding *vk_binding)
+{
+    struct vkd3d_shader_scan_info *scan_info = userdata;
+    if (binding->has_counter)
+    {
+        if (binding->d3d_binding.resource_index >= 8)
+            FIXME("DXIL shader attempts to use UAV counter for resource index >= 8.\n");
+        else
+            scan_info->uav_counter_mask |= 1u << binding->d3d_binding.resource_index;
+    }
+    return DXIL_SPV_TRUE;
+}
+
+int vkd3d_shader_scan_dxil(const struct vkd3d_shader_code *dxbc,
+        struct vkd3d_shader_scan_info *scan_info)
+{
+    dxil_spv_parsed_blob blob = NULL;
+    int ret = VKD3D_OK;
+
+    memset(scan_info, 0, sizeof(*scan_info));
+    if (dxil_spv_parse_dxil_blob(dxbc->code, dxbc->size, &blob) != DXIL_SPV_SUCCESS)
+    {
+        ret = VKD3D_ERROR_INVALID_SHADER;
+        goto end;
+    }
+
+    dxil_spv_parsed_blob_scan_resources(blob, NULL, NULL, NULL, dxil_uav_scan, scan_info);
+
+end:
+    dxil_spv_parsed_blob_free(blob);
+    return ret;
+}
+
+int vkd3d_shader_compile_dxil(const struct vkd3d_shader_code *dxbc,
+        struct vkd3d_shader_code *spirv,
+        const struct vkd3d_shader_interface_info *shader_interface_info,
+        const struct vkd3d_shader_compile_arguments *compiler_args)
+{
+    dxil_spv_parsed_blob blob = NULL;
+    dxil_spv_converter converter = NULL;
+    dxil_spv_compiled_spirv compiled;
+    void *code;
+    int ret = VKD3D_OK;
+    unsigned int i;
+    unsigned int root_constant_words = 0;
+    enum vkd3d_shader_type shader_type;
+    const struct vkd3d_shader_transform_feedback_info *xfb_info;
+
+    if (dxil_spv_parse_dxil_blob(dxbc->code, dxbc->size, &blob) != DXIL_SPV_SUCCESS)
+    {
+        ret = VKD3D_ERROR_INVALID_SHADER;
+        goto end;
+    }
+
+    switch (dxil_spv_parsed_blob_get_shader_stage(blob))
+    {
+        case DXIL_SPV_STAGE_VERTEX:
+            shader_type = VKD3D_SHADER_TYPE_VERTEX;
+            break;
+        case DXIL_SPV_STAGE_HULL:
+            shader_type = VKD3D_SHADER_TYPE_HULL;
+            break;
+        case DXIL_SPV_STAGE_DOMAIN:
+            shader_type = VKD3D_SHADER_TYPE_DOMAIN;
+            break;
+        case DXIL_SPV_STAGE_GEOMETRY:
+            shader_type = VKD3D_SHADER_TYPE_GEOMETRY;
+            break;
+        case DXIL_SPV_STAGE_PIXEL:
+            shader_type = VKD3D_SHADER_TYPE_PIXEL;
+            break;
+        case DXIL_SPV_STAGE_COMPUTE:
+            shader_type = VKD3D_SHADER_TYPE_COMPUTE;
+            break;
+        default:
+            ret = VKD3D_ERROR_INVALID_SHADER;
+            goto end;
+    }
+
+    vkd3d_shader_dump_shader(shader_type, dxbc);
+
+    if (dxil_spv_create_converter(blob, &converter) != DXIL_SPV_SUCCESS)
+    {
+        ret = VKD3D_ERROR_INVALID_SHADER;
+        goto end;
+    }
+
+    /* Figure out how many words we need for push constants. */
+    for (i = 0; i < shader_interface_info->push_constant_buffer_count; i++)
+    {
+        unsigned int max_size = shader_interface_info->push_constant_buffers[i].offset +
+                                shader_interface_info->push_constant_buffers[i].size;
+        max_size = (max_size + 3) / 4;
+        if (max_size > root_constant_words)
+            root_constant_words = max_size;
+    }
+
+    if (compiler_args)
+    {
+        for (i = 0; i < compiler_args->target_extension_count; i++)
+        {
+            if (compiler_args->target_extensions[i] == VKD3D_SHADER_TARGET_EXTENSION_SPV_EXT_DEMOTE_TO_HELPER_INVOCATION)
+            {
+                static const dxil_spv_option_shader_demote_to_helper helper =
+                        { { DXIL_SPV_OPTION_SHADER_DEMOTE_TO_HELPER }, DXIL_SPV_TRUE };
+                if (dxil_spv_converter_add_option(converter, &helper.base) != DXIL_SPV_SUCCESS)
+                {
+                    WARN("dxil-spirv does not support DEMOTE_TO_HELPER. Slower path will be used.\n");
+                }
+            }
+        }
+
+        if (compiler_args->dual_source_blending)
+        {
+            static const dxil_spv_option_dual_source_blending helper =
+                    { { DXIL_SPV_OPTION_DUAL_SOURCE_BLENDING }, DXIL_SPV_TRUE };
+            if (dxil_spv_converter_add_option(converter, &helper.base) != DXIL_SPV_SUCCESS)
+            {
+                ERR("dxil-spirv does not support DUAL_SOURCE_BLENDING.\n");
+                ret = VKD3D_ERROR_NOT_IMPLEMENTED;
+                goto end;
+            }
+        }
+    }
+
+    dxil_spv_converter_set_root_constant_word_count(converter, root_constant_words);
+    dxil_spv_converter_set_srv_remapper(converter, dxil_srv_remap, (void *)shader_interface_info);
+    dxil_spv_converter_set_sampler_remapper(converter, dxil_sampler_remap, (void *)shader_interface_info);
+    dxil_spv_converter_set_uav_remapper(converter, dxil_uav_remap, (void *)shader_interface_info);
+    dxil_spv_converter_set_cbv_remapper(converter, dxil_cbv_remap, (void *)shader_interface_info);
+    dxil_spv_converter_set_vertex_input_remapper(converter, dxil_input_remap, (void *)shader_interface_info);
+
+    xfb_info = vkd3d_find_struct(shader_interface_info->next, TRANSFORM_FEEDBACK_INFO);
+    if (xfb_info)
+        dxil_spv_converter_set_stream_output_remapper(converter, dxil_output_remap, (void *)xfb_info);
+
+    if (dxil_spv_converter_run(converter) != DXIL_SPV_SUCCESS)
+    {
+        ret = VKD3D_ERROR_INVALID_SHADER;
+        goto end;
+    }
+
+    if (dxil_spv_converter_get_compiled_spirv(converter, &compiled) != DXIL_SPV_SUCCESS)
+    {
+        ret = VKD3D_ERROR_INVALID_SHADER;
+        goto end;
+    }
+
+    if (!(code = vkd3d_malloc(compiled.size)))
+    {
+        ret = VKD3D_ERROR_OUT_OF_MEMORY;
+        goto end;
+    }
+
+    memcpy(code, compiled.data, compiled.size);
+    spirv->code = code;
+    spirv->size = compiled.size;
+
+    vkd3d_shader_dump_spirv_shader(shader_type, spirv);
+
+end:
+    dxil_spv_converter_free(converter);
+    dxil_spv_parsed_blob_free(blob);
+    return ret;
+}
+
diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c
index 70df19a..0a27665 100644
--- a/libs/vkd3d-shader/vkd3d_shader_main.c
+++ b/libs/vkd3d-shader/vkd3d_shader_main.c
@@ -168,6 +168,17 @@ int vkd3d_shader_compile_dxbc(const struct vkd3d_shader_code *dxbc,
     if ((ret = vkd3d_shader_validate_compile_args(compile_args)) < 0)
         return ret;
 
+    /* DXIL is handled externally through dxil-spirv. */
+    if (shader_is_dxil(dxbc->code, dxbc->size))
+    {
+#ifdef HAVE_DXIL_SPV
+        return vkd3d_shader_compile_dxil(dxbc, spirv, shader_interface_info, compile_args);
+#else
+        ERR("DXIL shader found, but DXIL support is not enabled in vkd3d.\n");
+        return VKD3D_ERROR_INVALID_SHADER;
+#endif
+    }
+
     scan_info.type = VKD3D_SHADER_STRUCTURE_TYPE_SCAN_INFO;
     scan_info.next = NULL;
     if ((ret = vkd3d_shader_scan_dxbc(dxbc, &scan_info)) < 0)
@@ -317,27 +328,39 @@ int vkd3d_shader_scan_dxbc(const struct vkd3d_shader_code *dxbc,
         return VKD3D_ERROR_INVALID_ARGUMENT;
     }
 
-    if ((ret = vkd3d_shader_parser_init(&parser, dxbc)) < 0)
-        return ret;
-
-    memset(scan_info, 0, sizeof(*scan_info));
-
-    while (!shader_sm4_is_end(parser.data, &parser.ptr))
+    if (shader_is_dxil(dxbc->code, dxbc->size))
     {
-        shader_sm4_read_instruction(parser.data, &parser.ptr, &instruction);
+#ifdef HAVE_DXIL_SPV
+        return vkd3d_shader_scan_dxil(dxbc, scan_info);
+#else
+        ERR("DXIL shader found, but DXIL support is not enabled in vkd3d.\n");
+        return VKD3D_ERROR_INVALID_SHADER;
+#endif
+    }
+    else
+    {
+        if ((ret = vkd3d_shader_parser_init(&parser, dxbc)) < 0)
+            return ret;
 
-        if (instruction.handler_idx == VKD3DSIH_INVALID)
+        memset(scan_info, 0, sizeof(*scan_info));
+
+        while (!shader_sm4_is_end(parser.data, &parser.ptr))
         {
-            WARN("Encountered unrecognized or invalid instruction.\n");
-            vkd3d_shader_parser_destroy(&parser);
-            return VKD3D_ERROR_INVALID_ARGUMENT;
+            shader_sm4_read_instruction(parser.data, &parser.ptr, &instruction);
+
+            if (instruction.handler_idx == VKD3DSIH_INVALID)
+            {
+                WARN("Encountered unrecognized or invalid instruction.\n");
+                vkd3d_shader_parser_destroy(&parser);
+                return VKD3D_ERROR_INVALID_ARGUMENT;
+            }
+
+            vkd3d_shader_scan_instruction(scan_info, &instruction);
         }
 
-        vkd3d_shader_scan_instruction(scan_info, &instruction);
+        vkd3d_shader_parser_destroy(&parser);
+        return VKD3D_OK;
     }
-
-    vkd3d_shader_parser_destroy(&parser);
-    return VKD3D_OK;
 }
 
 void vkd3d_shader_free_shader_code(struct vkd3d_shader_code *shader_code)
diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h
index e53475f..487fa0c 100644
--- a/libs/vkd3d-shader/vkd3d_shader_private.h
+++ b/libs/vkd3d-shader/vkd3d_shader_private.h
@@ -951,4 +951,12 @@ static inline const void *vkd3d_find_struct_(const struct vkd3d_struct *chain,
 #define VKD3D_DXBC_MAX_SOURCE_COUNT 6
 #define VKD3D_DXBC_HEADER_SIZE (8 * sizeof(uint32_t))
 
+/* DXIL support */
+int vkd3d_shader_scan_dxil(const struct vkd3d_shader_code *dxbc,
+        struct vkd3d_shader_scan_info *scan_info);
+int vkd3d_shader_compile_dxil(const struct vkd3d_shader_code *dxbc,
+        struct vkd3d_shader_code *spirv,
+        const struct vkd3d_shader_interface_info *shader_interface_info,
+        const struct vkd3d_shader_compile_arguments *compiler_args);
+
 #endif  /* __VKD3D_SHADER_PRIVATE_H */
-- 
2.25.0




More information about the wine-devel mailing list