• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © Microsoft Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23 
24 #include "dxil_spirv_nir.h"
25 #include "spirv_to_dxil.h"
26 #include "dxil_nir.h"
27 #include "nir_to_dxil.h"
28 #include "shader_enums.h"
29 #include "spirv/nir_spirv.h"
30 #include "util/blob.h"
31 
32 #include "git_sha1.h"
33 #include "vulkan/vulkan.h"
34 
35 static_assert(DXIL_SPIRV_SHADER_NONE == (int)MESA_SHADER_NONE, "must match");
36 static_assert(DXIL_SPIRV_SHADER_VERTEX == (int)MESA_SHADER_VERTEX, "must match");
37 static_assert(DXIL_SPIRV_SHADER_TESS_CTRL == (int)MESA_SHADER_TESS_CTRL, "must match");
38 static_assert(DXIL_SPIRV_SHADER_TESS_EVAL == (int)MESA_SHADER_TESS_EVAL, "must match");
39 static_assert(DXIL_SPIRV_SHADER_GEOMETRY == (int)MESA_SHADER_GEOMETRY, "must match");
40 static_assert(DXIL_SPIRV_SHADER_FRAGMENT == (int)MESA_SHADER_FRAGMENT, "must match");
41 static_assert(DXIL_SPIRV_SHADER_COMPUTE == (int)MESA_SHADER_COMPUTE, "must match");
42 static_assert(DXIL_SPIRV_SHADER_KERNEL == (int)MESA_SHADER_KERNEL, "must match");
43 
44 bool
spirv_to_dxil(const uint32_t * words,size_t word_count,struct dxil_spirv_specialization * specializations,unsigned int num_specializations,dxil_spirv_shader_stage stage,const char * entry_point_name,enum dxil_validator_version validator_version_max,const struct dxil_spirv_debug_options * dgb_opts,const struct dxil_spirv_runtime_conf * conf,const struct dxil_spirv_logger * logger,struct dxil_spirv_object * out_dxil)45 spirv_to_dxil(const uint32_t *words, size_t word_count,
46               struct dxil_spirv_specialization *specializations,
47               unsigned int num_specializations, dxil_spirv_shader_stage stage,
48               const char *entry_point_name,
49               enum dxil_validator_version validator_version_max,
50               const struct dxil_spirv_debug_options *dgb_opts,
51               const struct dxil_spirv_runtime_conf *conf,
52               const struct dxil_spirv_logger *logger,
53               struct dxil_spirv_object *out_dxil)
54 {
55    if (stage == DXIL_SPIRV_SHADER_NONE || stage == DXIL_SPIRV_SHADER_KERNEL)
56       return false;
57 
58    glsl_type_singleton_init_or_ref();
59 
60    struct nir_to_dxil_options opts = {
61       .environment = DXIL_ENVIRONMENT_VULKAN,
62       .shader_model_max = conf->shader_model_max,
63       .validator_version_max = validator_version_max,
64    };
65 
66    const struct spirv_to_nir_options *spirv_opts = dxil_spirv_nir_get_spirv_options();
67    nir_shader_compiler_options nir_options;
68    const unsigned supported_bit_sizes = 16 | 32 | 64;
69    dxil_get_nir_compiler_options(&nir_options, conf->shader_model_max, supported_bit_sizes, supported_bit_sizes);
70    // We will manually handle base_vertex when vertex_id and instance_id have
71    // have been already converted to zero-base.
72    nir_options.lower_base_vertex = conf->first_vertex_and_base_instance_mode != DXIL_SPIRV_SYSVAL_TYPE_ZERO;
73 
74    nir_shader *nir = spirv_to_nir(
75       words, word_count, (struct nir_spirv_specialization *)specializations,
76       num_specializations, (gl_shader_stage)stage, entry_point_name,
77       spirv_opts, &nir_options);
78    if (!nir) {
79       glsl_type_singleton_decref();
80       return false;
81    }
82 
83    nir_validate_shader(nir,
84                        "Validate before feeding NIR to the DXIL compiler");
85 
86    dxil_spirv_nir_prep(nir);
87 
88    dxil_spirv_nir_passes(nir, conf, &out_dxil->metadata);
89 
90    if (dgb_opts->dump_nir)
91       nir_print_shader(nir, stderr);
92 
93    struct dxil_logger logger_inner = {.priv = logger->priv,
94                                       .log = logger->log};
95 
96    struct blob dxil_blob;
97    if (!nir_to_dxil(nir, &opts, &logger_inner, &dxil_blob)) {
98       if (dxil_blob.allocated)
99          blob_finish(&dxil_blob);
100       ralloc_free(nir);
101       glsl_type_singleton_decref();
102       return false;
103    }
104 
105    ralloc_free(nir);
106    blob_finish_get_buffer(&dxil_blob, &out_dxil->binary.buffer,
107                           &out_dxil->binary.size);
108 
109    glsl_type_singleton_decref();
110    return true;
111 }
112 
113 void
spirv_to_dxil_free(struct dxil_spirv_object * dxil)114 spirv_to_dxil_free(struct dxil_spirv_object *dxil)
115 {
116    free(dxil->binary.buffer);
117 }
118 
119 uint64_t
spirv_to_dxil_get_version()120 spirv_to_dxil_get_version()
121 {
122    const char sha1[] = MESA_GIT_SHA1;
123    const char* dash = strchr(sha1, '-');
124    if (dash) {
125       return strtoull(dash + 1, NULL, 16);
126    }
127    return 0;
128 }
129