Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/microsoft/spirv_to_dxil/spirv_to_dxil.c
4564 views
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 "spirv_to_dxil.h"
25
#include "nir_to_dxil.h"
26
#include "dxil_nir.h"
27
#include "shader_enums.h"
28
#include "spirv/nir_spirv.h"
29
#include "util/blob.h"
30
31
bool
32
spirv_to_dxil(const uint32_t *words, size_t word_count,
33
struct dxil_spirv_specialization *specializations,
34
unsigned int num_specializations, dxil_spirv_shader_stage stage,
35
const char *entry_point_name, void **buffer, size_t *size)
36
{
37
if (stage == MESA_SHADER_NONE || stage == MESA_SHADER_KERNEL)
38
return false;
39
40
struct spirv_to_nir_options spirv_opts = {
41
.ubo_addr_format = nir_address_format_32bit_index_offset,
42
.ssbo_addr_format = nir_address_format_32bit_index_offset,
43
// use_deref_buffer_array_length + nir_lower_explicit_io force
44
// get_ssbo_size to take in the return from load_vulkan_descriptor
45
// instead of vulkan_resource_index. This makes it much easier to
46
// get the DXIL handle for the SSBO.
47
.use_deref_buffer_array_length = true
48
};
49
50
glsl_type_singleton_init_or_ref();
51
52
struct nir_shader_compiler_options nir_options = *dxil_get_nir_compiler_options();
53
// We will manually handle base_vertex
54
nir_options.lower_base_vertex = false;
55
56
nir_shader *nir = spirv_to_nir(
57
words, word_count, (struct nir_spirv_specialization *)specializations,
58
num_specializations, (gl_shader_stage)stage, entry_point_name,
59
&spirv_opts, &nir_options);
60
if (!nir) {
61
glsl_type_singleton_decref();
62
return false;
63
}
64
65
nir_validate_shader(nir,
66
"Validate before feeding NIR to the DXIL compiler");
67
68
NIR_PASS_V(nir, nir_lower_system_values);
69
70
// vertex_id and instance_id should have already been transformed to base
71
// zero before spirv_to_dxil was called. Also, WebGPU does not support
72
// base/firstVertex/Instance.
73
gl_system_value system_values[] = {
74
SYSTEM_VALUE_FIRST_VERTEX,
75
SYSTEM_VALUE_BASE_VERTEX,
76
SYSTEM_VALUE_BASE_INSTANCE
77
};
78
NIR_PASS_V(nir, dxil_nir_lower_system_values_to_zero, system_values, ARRAY_SIZE(system_values));
79
80
NIR_PASS_V(nir, nir_split_per_member_structs);
81
82
NIR_PASS_V(nir, nir_lower_explicit_io, nir_var_mem_ubo | nir_var_mem_ssbo,
83
nir_address_format_32bit_index_offset);
84
85
nir_variable_mode nir_var_function_temp =
86
nir_var_shader_in | nir_var_shader_out;
87
NIR_PASS_V(nir, nir_lower_variable_initializers,
88
nir_var_function_temp);
89
NIR_PASS_V(nir, nir_opt_deref);
90
NIR_PASS_V(nir, nir_lower_returns);
91
NIR_PASS_V(nir, nir_inline_functions);
92
NIR_PASS_V(nir, nir_lower_variable_initializers,
93
~nir_var_function_temp);
94
95
// Pick off the single entrypoint that we want.
96
nir_function *entrypoint;
97
foreach_list_typed_safe(nir_function, func, node, &nir->functions) {
98
if (func->is_entrypoint)
99
entrypoint = func;
100
else
101
exec_node_remove(&func->node);
102
}
103
assert(exec_list_length(&nir->functions) == 1);
104
105
NIR_PASS_V(nir, nir_lower_clip_cull_distance_arrays);
106
NIR_PASS_V(nir, nir_lower_io_to_temporaries, entrypoint->impl, true, true);
107
NIR_PASS_V(nir, nir_lower_global_vars_to_local);
108
NIR_PASS_V(nir, nir_split_var_copies);
109
NIR_PASS_V(nir, nir_lower_var_copies);
110
NIR_PASS_V(nir, nir_lower_io_arrays_to_elements_no_indirects, false);
111
112
NIR_PASS_V(nir, nir_lower_alu_to_scalar, NULL, NULL);
113
NIR_PASS_V(nir, nir_opt_dce);
114
NIR_PASS_V(nir, dxil_nir_lower_double_math);
115
116
{
117
bool progress;
118
do
119
{
120
progress = false;
121
NIR_PASS(progress, nir, nir_copy_prop);
122
NIR_PASS(progress, nir, nir_opt_copy_prop_vars);
123
NIR_PASS(progress, nir, nir_opt_deref);
124
NIR_PASS(progress, nir, nir_opt_dce);
125
NIR_PASS(progress, nir, nir_opt_undef);
126
NIR_PASS(progress, nir, nir_opt_constant_folding);
127
NIR_PASS(progress, nir, nir_opt_cse);
128
NIR_PASS(progress, nir, nir_lower_vars_to_ssa);
129
NIR_PASS(progress, nir, nir_opt_algebraic);
130
} while (progress);
131
}
132
133
NIR_PASS_V(nir, nir_lower_readonly_images_to_tex, true);
134
NIR_PASS_V(nir, dxil_nir_split_clip_cull_distance);
135
NIR_PASS_V(nir, dxil_nir_lower_loads_stores_to_dxil);
136
NIR_PASS_V(nir, dxil_nir_create_bare_samplers);
137
138
nir_shader_gather_info(nir, nir_shader_get_entrypoint(nir));
139
140
nir->info.inputs_read =
141
dxil_reassign_driver_locations(nir, nir_var_shader_in, 0);
142
143
if (stage != MESA_SHADER_FRAGMENT) {
144
nir->info.outputs_written =
145
dxil_reassign_driver_locations(nir, nir_var_shader_out, 0);
146
} else {
147
dxil_sort_ps_outputs(nir);
148
}
149
150
struct nir_to_dxil_options opts = {.vulkan_environment = true};
151
152
struct blob dxil_blob;
153
if (!nir_to_dxil(nir, &opts, &dxil_blob)) {
154
if (dxil_blob.allocated)
155
blob_finish(&dxil_blob);
156
glsl_type_singleton_decref();
157
return false;
158
}
159
160
blob_finish_get_buffer(&dxil_blob, buffer, size);
161
162
glsl_type_singleton_decref();
163
return true;
164
}
165
166
void
167
spirv_to_dxil_free(void* buffer)
168
{
169
free(buffer);
170
}
171
172