2 * Copyright 2018 Collabora Ltd.
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 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
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
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 NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE.
24 #include "zink_compiler.h"
25 #include "zink_screen.h"
26 #include "nir_to_spirv/nir_to_spirv.h"
28 #include "pipe/p_state.h"
31 #include "compiler/nir/nir_builder.h"
33 #include "nir/tgsi_to_nir.h"
34 #include "tgsi/tgsi_dump.h"
35 #include "tgsi/tgsi_from_mesa.h"
37 #include "util/u_memory.h"
40 lower_instr(nir_intrinsic_instr
*instr
, nir_builder
*b
)
42 b
->cursor
= nir_before_instr(&instr
->instr
);
44 if (instr
->intrinsic
== nir_intrinsic_load_ubo
) {
45 nir_ssa_def
*old_idx
= nir_ssa_for_src(b
, instr
->src
[0], 1);
46 nir_ssa_def
*new_idx
= nir_iadd(b
, old_idx
, nir_imm_int(b
, 1));
47 nir_instr_rewrite_src(&instr
->instr
, &instr
->src
[0],
48 nir_src_for_ssa(new_idx
));
52 if (instr
->intrinsic
== nir_intrinsic_load_uniform
) {
53 nir_ssa_def
*ubo_idx
= nir_imm_int(b
, 0);
54 nir_ssa_def
*ubo_offset
=
55 nir_iadd(b
, nir_imm_int(b
, nir_intrinsic_base(instr
)),
56 nir_ssa_for_src(b
, instr
->src
[0], 1));
58 nir_intrinsic_instr
*load
=
59 nir_intrinsic_instr_create(b
->shader
, nir_intrinsic_load_ubo
);
60 load
->num_components
= instr
->num_components
;
61 load
->src
[0] = nir_src_for_ssa(ubo_idx
);
62 load
->src
[1] = nir_src_for_ssa(ubo_offset
);
63 nir_ssa_dest_init(&load
->instr
, &load
->dest
,
64 load
->num_components
, instr
->dest
.ssa
.bit_size
,
65 instr
->dest
.ssa
.name
);
66 nir_builder_instr_insert(b
, &load
->instr
);
67 nir_ssa_def_rewrite_uses(&instr
->dest
.ssa
, nir_src_for_ssa(&load
->dest
.ssa
));
69 nir_instr_remove(&instr
->instr
);
77 lower_uniforms_to_ubo(nir_shader
*shader
)
79 bool progress
= false;
81 nir_foreach_function(function
, shader
) {
84 nir_builder_init(&builder
, function
->impl
);
85 nir_foreach_block(block
, function
->impl
) {
86 nir_foreach_instr_safe(instr
, block
) {
87 if (instr
->type
== nir_instr_type_intrinsic
)
88 progress
|= lower_instr(nir_instr_as_intrinsic(instr
),
93 nir_metadata_preserve(function
->impl
, nir_metadata_block_index
|
94 nir_metadata_dominance
);
99 assert(shader
->num_uniforms
> 0);
100 const struct glsl_type
*type
= glsl_array_type(glsl_vec4_type(),
101 shader
->num_uniforms
, 0);
102 nir_variable
*ubo
= nir_variable_create(shader
, nir_var_mem_ubo
, type
,
104 ubo
->data
.binding
= 0;
106 struct glsl_struct_field field
= {
111 ubo
->interface_type
=
112 glsl_interface_type(&field
, 1, GLSL_INTERFACE_PACKING_STD430
,
113 false, "__ubo0_interface");
120 lower_pos_write(nir_builder
*b
, struct nir_instr
*instr
)
122 if (instr
->type
!= nir_instr_type_intrinsic
)
125 nir_intrinsic_instr
*intr
= nir_instr_as_intrinsic(instr
);
127 if (intr
->intrinsic
== nir_intrinsic_store_output
) {
128 if (nir_intrinsic_base(intr
) != VARYING_SLOT_POS
)
131 } else if (intr
->intrinsic
== nir_intrinsic_store_deref
) {
132 nir_variable
*var
= nir_intrinsic_get_var(intr
, 0);
133 if (var
->data
.mode
!= nir_var_shader_out
||
134 var
->data
.location
!= VARYING_SLOT_POS
)
140 b
->cursor
= nir_before_instr(&intr
->instr
);
142 nir_ssa_def
*pos
= nir_ssa_for_src(b
, *src
, 4);
143 nir_ssa_def
*def
= nir_vec4(b
,
144 nir_channel(b
, pos
, 0),
145 nir_channel(b
, pos
, 1),
148 nir_channel(b
, pos
, 2),
149 nir_channel(b
, pos
, 3)),
150 nir_imm_float(b
, 0.5)),
151 nir_channel(b
, pos
, 3));
152 nir_instr_rewrite_src(&intr
->instr
, src
, nir_src_for_ssa(def
));
156 lower_clip_halfz(nir_shader
*s
)
158 if (s
->info
.stage
!= MESA_SHADER_VERTEX
)
161 nir_foreach_function(function
, s
) {
162 if (function
->impl
) {
164 nir_builder_init(&b
, function
->impl
);
166 nir_foreach_block(block
, function
->impl
) {
167 nir_foreach_instr_safe(instr
, block
) {
168 lower_pos_write(&b
, instr
);
172 nir_metadata_preserve(function
->impl
, nir_metadata_block_index
|
173 nir_metadata_dominance
);
179 lower_discard_if_instr(nir_intrinsic_instr
*instr
, nir_builder
*b
)
181 if (instr
->intrinsic
== nir_intrinsic_discard_if
) {
182 b
->cursor
= nir_before_instr(&instr
->instr
);
184 nir_if
*if_stmt
= nir_push_if(b
, nir_ssa_for_src(b
, instr
->src
[0], 1));
185 nir_intrinsic_instr
*discard
=
186 nir_intrinsic_instr_create(b
->shader
, nir_intrinsic_discard
);
187 nir_builder_instr_insert(b
, &discard
->instr
);
188 nir_pop_if(b
, if_stmt
);
189 nir_instr_remove(&instr
->instr
);
192 assert(instr
->intrinsic
!= nir_intrinsic_discard
||
193 nir_block_last_instr(instr
->instr
.block
) == &instr
->instr
);
199 lower_discard_if(nir_shader
*shader
)
201 bool progress
= false;
203 nir_foreach_function(function
, shader
) {
204 if (function
->impl
) {
206 nir_builder_init(&builder
, function
->impl
);
207 nir_foreach_block(block
, function
->impl
) {
208 nir_foreach_instr_safe(instr
, block
) {
209 if (instr
->type
== nir_instr_type_intrinsic
)
210 progress
|= lower_discard_if_instr(
211 nir_instr_as_intrinsic(instr
),
216 nir_metadata_preserve(function
->impl
, nir_metadata_dominance
);
223 static const struct nir_shader_compiler_options nir_options
= {
224 .lower_all_io_to_temps
= true,
226 .lower_flrp32
= true,
232 zink_get_compiler_options(struct pipe_screen
*screen
,
233 enum pipe_shader_ir ir
,
234 enum pipe_shader_type shader
)
236 assert(ir
== PIPE_SHADER_IR_NIR
);
241 zink_tgsi_to_nir(struct pipe_screen
*screen
, const struct tgsi_token
*tokens
)
243 if (zink_debug
& ZINK_DEBUG_TGSI
) {
244 fprintf(stderr
, "TGSI shader:\n---8<---\n");
245 tgsi_dump_to_file(tokens
, 0, stderr
);
246 fprintf(stderr
, "---8<---\n\n");
249 return tgsi_to_nir(tokens
, screen
);
253 optimize_nir(struct nir_shader
*s
)
258 NIR_PASS_V(s
, nir_lower_vars_to_ssa
);
259 NIR_PASS(progress
, s
, nir_copy_prop
);
260 NIR_PASS(progress
, s
, nir_opt_remove_phis
);
261 NIR_PASS(progress
, s
, nir_opt_dce
);
262 NIR_PASS(progress
, s
, nir_opt_dead_cf
);
263 NIR_PASS(progress
, s
, nir_opt_cse
);
264 NIR_PASS(progress
, s
, nir_opt_peephole_select
, 8, true, true);
265 NIR_PASS(progress
, s
, nir_opt_algebraic
);
266 NIR_PASS(progress
, s
, nir_opt_constant_folding
);
267 NIR_PASS(progress
, s
, nir_opt_undef
);
272 zink_binding(enum pipe_shader_type stage
, VkDescriptorType type
, int index
)
274 if (stage
== PIPE_SHADER_COMPUTE
) {
275 unreachable("not supported");
277 uint32_t stage_offset
= (uint32_t)stage
* (PIPE_MAX_CONSTANT_BUFFERS
+
278 PIPE_MAX_SHADER_SAMPLER_VIEWS
);
281 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER
:
282 assert(index
< PIPE_MAX_CONSTANT_BUFFERS
);
283 return stage_offset
+ index
;
285 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER
:
286 assert(index
< PIPE_MAX_SHADER_SAMPLER_VIEWS
);
287 return stage_offset
+ PIPE_MAX_CONSTANT_BUFFERS
+ index
;
290 unreachable("unexpected type");
296 zink_compile_nir(struct zink_screen
*screen
, struct nir_shader
*nir
)
298 struct zink_shader
*ret
= CALLOC_STRUCT(zink_shader
);
300 NIR_PASS_V(nir
, lower_uniforms_to_ubo
);
301 NIR_PASS_V(nir
, lower_clip_halfz
);
302 NIR_PASS_V(nir
, nir_lower_regs_to_ssa
);
304 NIR_PASS_V(nir
, nir_remove_dead_variables
, nir_var_function_temp
);
305 NIR_PASS_V(nir
, lower_discard_if
);
306 NIR_PASS_V(nir
, nir_convert_from_ssa
, true);
308 if (zink_debug
& ZINK_DEBUG_NIR
) {
309 fprintf(stderr
, "NIR shader:\n---8<---\n");
310 nir_print_shader(nir
, stderr
);
311 fprintf(stderr
, "---8<---\n");
314 enum pipe_shader_type stage
= pipe_shader_type_from_mesa(nir
->info
.stage
);
316 ret
->num_bindings
= 0;
317 nir_foreach_variable(var
, &nir
->uniforms
) {
318 if (glsl_type_is_sampler(var
->type
)) {
319 ret
->bindings
[ret
->num_bindings
].index
= var
->data
.driver_location
;
320 var
->data
.binding
= zink_binding(stage
, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER
, var
->data
.driver_location
);
321 ret
->bindings
[ret
->num_bindings
].binding
= var
->data
.binding
;
322 ret
->bindings
[ret
->num_bindings
].type
= VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER
;
324 } else if (var
->interface_type
) {
325 ret
->bindings
[ret
->num_bindings
].index
= var
->data
.binding
;
326 var
->data
.binding
= zink_binding(stage
, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER
, var
->data
.binding
);
327 ret
->bindings
[ret
->num_bindings
].binding
= var
->data
.binding
;
328 ret
->bindings
[ret
->num_bindings
].type
= VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER
;
333 ret
->info
= nir
->info
;
335 struct spirv_shader
*spirv
= nir_to_spirv(nir
);
338 if (zink_debug
& ZINK_DEBUG_SPIRV
) {
341 snprintf(buf
, sizeof(buf
), "dump%02d.spv", i
++);
342 FILE *fp
= fopen(buf
, "wb");
343 fwrite(spirv
->words
, sizeof(uint32_t), spirv
->num_words
, fp
);
345 fprintf(stderr
, "wrote '%s'...\n", buf
);
348 VkShaderModuleCreateInfo smci
= {};
349 smci
.sType
= VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO
;
350 smci
.codeSize
= spirv
->num_words
* sizeof(uint32_t);
351 smci
.pCode
= spirv
->words
;
353 if (vkCreateShaderModule(screen
->dev
, &smci
, NULL
, &ret
->shader_module
) != VK_SUCCESS
)
360 zink_shader_free(struct zink_screen
*screen
, struct zink_shader
*shader
)
362 vkDestroyShaderModule(screen
->dev
, shader
->shader_module
, NULL
);