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