xref: /aosp_15_r20/external/mesa3d/src/microsoft/spirv_to_dxil/spirv_to_dxil.h (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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 #ifndef SPIRV_TO_DXIL_H
25 #define SPIRV_TO_DXIL_H
26 
27 #include "dxil_versions.h"
28 
29 #include <stdbool.h>
30 #include <stddef.h>
31 #include <stdint.h>
32 
33 #ifdef __cplusplus
34 extern "C" {
35 #endif
36 
37 // NB: I've copy and pasted some types into this header so we don't have to
38 // include other headers. This will surely break if any of these types change.
39 
40 // Copy of gl_shader_stage
41 typedef enum {
42    DXIL_SPIRV_SHADER_NONE = -1,
43    DXIL_SPIRV_SHADER_VERTEX = 0,
44    DXIL_SPIRV_SHADER_TESS_CTRL = 1,
45    DXIL_SPIRV_SHADER_TESS_EVAL = 2,
46    DXIL_SPIRV_SHADER_GEOMETRY = 3,
47    DXIL_SPIRV_SHADER_FRAGMENT = 4,
48    DXIL_SPIRV_SHADER_COMPUTE = 5,
49    DXIL_SPIRV_SHADER_KERNEL = 14,
50 } dxil_spirv_shader_stage;
51 
52 // Copy of nir_spirv_const_value
53 typedef union {
54    bool b;
55    float f32;
56    double f64;
57    int8_t i8;
58    uint8_t u8;
59    int16_t i16;
60    uint16_t u16;
61    int32_t i32;
62    uint32_t u32;
63    int64_t i64;
64    uint64_t u64;
65 } dxil_spirv_const_value;
66 
67 // Copy of nir_spirv_specialization
68 struct dxil_spirv_specialization {
69    uint32_t id;
70    dxil_spirv_const_value value;
71    bool defined_on_module;
72 };
73 
74 struct dxil_spirv_metadata {
75    // Some sysval or other type of data is accessed which needs to be piped
76    // from the app/API implementation into the shader via a buffer
77    bool requires_runtime_data;
78 
79    // Specifically if a vertex shader needs the first-vertex or base-instance
80    // sysval. These are relevant since these can come from an indirect arg
81    // buffer, and therefore piping them to the runtime data buffer is extra
82    // complex.
83    bool needs_draw_sysvals;
84 };
85 
86 struct dxil_spirv_object {
87    struct dxil_spirv_metadata metadata;
88    struct {
89       void *buffer;
90       size_t size;
91    } binary;
92 };
93 
94 /* This struct describes the layout of data expected in the CB bound to
95  * runtime_data_cbv during compute shader execution */
96 struct dxil_spirv_compute_runtime_data {
97    /* Total number of groups dispatched (i.e. value passed to Dispatch()) */
98    uint32_t group_count_x;
99    uint32_t group_count_y;
100    uint32_t group_count_z;
101    uint32_t padding0;
102    /* Base */
103    uint32_t base_group_x;
104    uint32_t base_group_y;
105    uint32_t base_group_z;
106 };
107 
108 #define DXIL_SPIRV_Y_FLIP_MASK BITFIELD_MASK(DXIL_SPIRV_MAX_VIEWPORT)
109 #define DXIL_SPIRV_Z_FLIP_SHIFT DXIL_SPIRV_MAX_VIEWPORT
110 #define DXIL_SPIRV_Z_FLIP_MASK BITFIELD_RANGE(DXIL_SPIRV_Z_FLIP_SHIFT, DXIL_SPIRV_MAX_VIEWPORT)
111 
112 /* This struct describes the layout of data expected in the CB bound to
113  * runtime_data_cbv during vertex stages */
114 struct dxil_spirv_vertex_runtime_data {
115    uint32_t first_vertex;
116    uint32_t base_instance;
117    bool is_indexed_draw;
118    // The lower 16bits of this mask encode Y-flips (one bit per viewport)
119    // The higher 16bits of this maks encode Z-flips (one bit per viewport)
120    union {
121       uint32_t yz_flip_mask;
122       struct {
123          uint16_t y_flip_mask;
124          uint16_t z_flip_mask;
125       };
126    };
127    uint32_t draw_id;
128    float viewport_width;
129    float viewport_height;
130    uint32_t view_index;
131    /* When depth bias is dynamic, the constant value to add to point
132     * primitives when emulating triangle point fill mode. Slope-scaled
133     * depth bias is currently unsupported. */
134    float depth_bias;
135 };
136 
137 enum dxil_spirv_yz_flip_mode {
138    DXIL_SPIRV_YZ_FLIP_NONE = 0,
139    // Y-flip is unconditional: pos.y = -pos.y
140    // Z-flip is unconditional: pos.z = -pos.z + 1.0f
141    DXIL_SPIRV_Y_FLIP_UNCONDITIONAL = 1 << 0,
142    DXIL_SPIRV_Z_FLIP_UNCONDITIONAL = 1 << 1,
143    DXIL_SPIRV_YZ_FLIP_UNCONDITIONAL = DXIL_SPIRV_Y_FLIP_UNCONDITIONAL | DXIL_SPIRV_Z_FLIP_UNCONDITIONAL,
144    // Y-flip/Z-flip info are passed through a sysval
145    DXIL_SPIRV_Y_FLIP_CONDITIONAL = 1 << 2,
146    DXIL_SPIRV_Z_FLIP_CONDITIONAL = 1 << 3,
147    DXIL_SPIRV_YZ_FLIP_CONDITIONAL = DXIL_SPIRV_Y_FLIP_CONDITIONAL | DXIL_SPIRV_Z_FLIP_CONDITIONAL,
148 };
149 
150 #define DXIL_SPIRV_MAX_VIEWPORT 16
151 
152 enum dxil_spirv_sysval_type {
153    // The sysval can be inlined in the shader as a constant zero
154    DXIL_SPIRV_SYSVAL_TYPE_ZERO,
155    // The sysval has a supported DXIL equivalent
156    DXIL_SPIRV_SYSVAL_TYPE_NATIVE,
157    // The sysval might be nonzero and has no DXIL equivalent, so it
158    // will need to be provided by the runtime_data constant buffer
159    DXIL_SPIRV_SYSVAL_TYPE_RUNTIME_DATA,
160 };
161 
162 struct dxil_spirv_runtime_conf {
163    struct {
164       uint32_t register_space;
165       uint32_t base_shader_register;
166    } runtime_data_cbv;
167 
168    struct {
169       uint32_t register_space;
170       uint32_t base_shader_register;
171    } push_constant_cbv;
172 
173    enum dxil_spirv_sysval_type first_vertex_and_base_instance_mode;
174    enum dxil_spirv_sysval_type workgroup_id_mode;
175 
176    struct {
177       // mode != DXIL_SPIRV_YZ_FLIP_NONE only valid on vertex/geometry stages.
178       enum dxil_spirv_yz_flip_mode mode;
179 
180       // Y/Z flip masks (one bit per viewport)
181       uint16_t y_mask;
182       uint16_t z_mask;
183    } yz_flip;
184 
185    // The caller supports read-only images to be turned into SRV accesses,
186    // which allows us to run the nir_opt_access() pass
187    bool declared_read_only_images_as_srvs;
188 
189    // The caller supports read-write images to be turned into SRV accesses,
190    // if they are found not to be written
191    bool inferred_read_only_images_as_srvs;
192 
193    // Force sample rate shading on a fragment shader
194    bool force_sample_rate_shading;
195 
196    // View index needs to be lowered to a UBO lookup
197    bool lower_view_index;
198    // View index also needs to be forwarded to RT layer output
199    bool lower_view_index_to_rt_layer;
200 
201    // Affects which features can be used by the shader
202    enum dxil_shader_model shader_model_max;
203 };
204 
205 struct dxil_spirv_debug_options {
206    bool dump_nir;
207 };
208 
209 typedef void (*dxil_spirv_msg_callback)(void *priv, const char *msg);
210 
211 struct dxil_spirv_logger {
212    void *priv;
213    dxil_spirv_msg_callback log;
214 };
215 
216 /**
217  * Compile a SPIR-V module into DXIL.
218  * \param  words  SPIR-V module to compile
219  * \param  word_count  number of words in the SPIR-V module
220  * \param  specializations  specialization constants to compile with the shader
221  * \param  num_specializations  number of specialization constants
222  * \param  stage  shader stage
223  * \param  entry_point_name  name of shader entrypoint
224  * \param  conf  configuration for spriv_to_dxil
225  * \param  out_dxil  will contain the DXIL bytes on success (call spirv_to_dxil_free after use)
226  * \return  true if compilation succeeded
227  */
228 bool
229 spirv_to_dxil(const uint32_t *words, size_t word_count,
230               struct dxil_spirv_specialization *specializations,
231               unsigned int num_specializations, dxil_spirv_shader_stage stage,
232               const char *entry_point_name,
233               enum dxil_validator_version validator_version_max,
234               const struct dxil_spirv_debug_options *debug_options,
235               const struct dxil_spirv_runtime_conf *conf,
236               const struct dxil_spirv_logger *logger,
237               struct dxil_spirv_object *out_dxil);
238 
239 /**
240  * Free the buffer allocated by spirv_to_dxil.
241  */
242 void
243 spirv_to_dxil_free(struct dxil_spirv_object *dxil);
244 
245 uint64_t
246 spirv_to_dxil_get_version(void);
247 
248 #ifdef __cplusplus
249 }
250 #endif
251 
252 #endif
253