zink: track program usages for each shader
[mesa.git] / src / gallium / drivers / zink / zink_compiler.c
1 /*
2 * Copyright 2018 Collabora Ltd.
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 * 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:
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 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.
22 */
23
24 #include "zink_compiler.h"
25 #include "zink_program.h"
26 #include "zink_screen.h"
27 #include "nir_to_spirv/nir_to_spirv.h"
28
29 #include "pipe/p_state.h"
30
31 #include "nir.h"
32 #include "compiler/nir/nir_builder.h"
33
34 #include "nir/tgsi_to_nir.h"
35 #include "tgsi/tgsi_dump.h"
36 #include "tgsi/tgsi_from_mesa.h"
37
38 #include "util/u_memory.h"
39
40 static bool
41 lower_discard_if_instr(nir_intrinsic_instr *instr, nir_builder *b)
42 {
43 if (instr->intrinsic == nir_intrinsic_discard_if) {
44 b->cursor = nir_before_instr(&instr->instr);
45
46 nir_if *if_stmt = nir_push_if(b, nir_ssa_for_src(b, instr->src[0], 1));
47 nir_intrinsic_instr *discard =
48 nir_intrinsic_instr_create(b->shader, nir_intrinsic_discard);
49 nir_builder_instr_insert(b, &discard->instr);
50 nir_pop_if(b, if_stmt);
51 nir_instr_remove(&instr->instr);
52 return true;
53 }
54 assert(instr->intrinsic != nir_intrinsic_discard ||
55 nir_block_last_instr(instr->instr.block) == &instr->instr);
56
57 return false;
58 }
59
60 static bool
61 lower_discard_if(nir_shader *shader)
62 {
63 bool progress = false;
64
65 nir_foreach_function(function, shader) {
66 if (function->impl) {
67 nir_builder builder;
68 nir_builder_init(&builder, function->impl);
69 nir_foreach_block(block, function->impl) {
70 nir_foreach_instr_safe(instr, block) {
71 if (instr->type == nir_instr_type_intrinsic)
72 progress |= lower_discard_if_instr(
73 nir_instr_as_intrinsic(instr),
74 &builder);
75 }
76 }
77
78 nir_metadata_preserve(function->impl, nir_metadata_dominance);
79 }
80 }
81
82 return progress;
83 }
84
85 static const struct nir_shader_compiler_options nir_options = {
86 .lower_all_io_to_temps = true,
87 .lower_ffma = true,
88 .lower_fdph = true,
89 .lower_flrp32 = true,
90 .lower_fpow = true,
91 .lower_fsat = true,
92 };
93
94 const void *
95 zink_get_compiler_options(struct pipe_screen *screen,
96 enum pipe_shader_ir ir,
97 enum pipe_shader_type shader)
98 {
99 assert(ir == PIPE_SHADER_IR_NIR);
100 return &nir_options;
101 }
102
103 struct nir_shader *
104 zink_tgsi_to_nir(struct pipe_screen *screen, const struct tgsi_token *tokens)
105 {
106 if (zink_debug & ZINK_DEBUG_TGSI) {
107 fprintf(stderr, "TGSI shader:\n---8<---\n");
108 tgsi_dump_to_file(tokens, 0, stderr);
109 fprintf(stderr, "---8<---\n\n");
110 }
111
112 return tgsi_to_nir(tokens, screen, false);
113 }
114
115 static void
116 optimize_nir(struct nir_shader *s)
117 {
118 bool progress;
119 do {
120 progress = false;
121 NIR_PASS_V(s, nir_lower_vars_to_ssa);
122 NIR_PASS(progress, s, nir_copy_prop);
123 NIR_PASS(progress, s, nir_opt_remove_phis);
124 NIR_PASS(progress, s, nir_opt_dce);
125 NIR_PASS(progress, s, nir_opt_dead_cf);
126 NIR_PASS(progress, s, nir_opt_cse);
127 NIR_PASS(progress, s, nir_opt_peephole_select, 8, true, true);
128 NIR_PASS(progress, s, nir_opt_algebraic);
129 NIR_PASS(progress, s, nir_opt_constant_folding);
130 NIR_PASS(progress, s, nir_opt_undef);
131 NIR_PASS(progress, s, zink_nir_lower_b2b);
132 } while (progress);
133 }
134
135 struct zink_shader *
136 zink_compile_nir(struct zink_screen *screen, struct nir_shader *nir)
137 {
138 struct zink_shader *ret = CALLOC_STRUCT(zink_shader);
139
140 ret->programs = _mesa_pointer_set_create(NULL);
141
142 NIR_PASS_V(nir, nir_lower_uniforms_to_ubo, 1);
143 NIR_PASS_V(nir, nir_lower_clip_halfz);
144 NIR_PASS_V(nir, nir_lower_regs_to_ssa);
145 optimize_nir(nir);
146 NIR_PASS_V(nir, nir_remove_dead_variables, nir_var_function_temp, NULL);
147 NIR_PASS_V(nir, lower_discard_if);
148 NIR_PASS_V(nir, nir_convert_from_ssa, true);
149
150 if (zink_debug & ZINK_DEBUG_NIR) {
151 fprintf(stderr, "NIR shader:\n---8<---\n");
152 nir_print_shader(nir, stderr);
153 fprintf(stderr, "---8<---\n");
154 }
155
156 ret->num_bindings = 0;
157 nir_foreach_variable(var, &nir->uniforms) {
158 if (var->data.mode == nir_var_mem_ubo) {
159 int binding = zink_binding(nir->info.stage,
160 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
161 var->data.binding);
162 ret->bindings[ret->num_bindings].index = var->data.binding;
163 ret->bindings[ret->num_bindings].binding = binding;
164 ret->bindings[ret->num_bindings].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
165 ret->num_bindings++;
166 } else {
167 assert(var->data.mode == nir_var_uniform);
168 if (glsl_type_is_array(var->type) &&
169 glsl_type_is_sampler(glsl_get_array_element(var->type))) {
170 for (int i = 0; i < glsl_get_length(var->type); ++i) {
171 int binding = zink_binding(nir->info.stage,
172 VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
173 var->data.binding + i);
174 ret->bindings[ret->num_bindings].index = var->data.binding + i;
175 ret->bindings[ret->num_bindings].binding = binding;
176 ret->bindings[ret->num_bindings].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
177 ret->num_bindings++;
178 }
179 } else if (glsl_type_is_sampler(var->type)) {
180 int binding = zink_binding(nir->info.stage,
181 VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
182 var->data.binding);
183 ret->bindings[ret->num_bindings].index = var->data.binding;
184 ret->bindings[ret->num_bindings].binding = binding;
185 ret->bindings[ret->num_bindings].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
186 ret->num_bindings++;
187 }
188 }
189 }
190
191 ret->info = nir->info;
192
193 struct spirv_shader *spirv = nir_to_spirv(nir);
194 assert(spirv);
195
196 if (zink_debug & ZINK_DEBUG_SPIRV) {
197 char buf[256];
198 static int i;
199 snprintf(buf, sizeof(buf), "dump%02d.spv", i++);
200 FILE *fp = fopen(buf, "wb");
201 if (fp) {
202 fwrite(spirv->words, sizeof(uint32_t), spirv->num_words, fp);
203 fclose(fp);
204 fprintf(stderr, "wrote '%s'...\n", buf);
205 }
206 }
207
208 VkShaderModuleCreateInfo smci = {};
209 smci.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
210 smci.codeSize = spirv->num_words * sizeof(uint32_t);
211 smci.pCode = spirv->words;
212
213 if (vkCreateShaderModule(screen->dev, &smci, NULL, &ret->shader_module) != VK_SUCCESS)
214 return NULL;
215
216 return ret;
217 }
218
219 void
220 zink_shader_free(struct zink_screen *screen, struct zink_shader *shader)
221 {
222 vkDestroyShaderModule(screen->dev, shader->shader_module, NULL);
223 set_foreach(shader->programs, entry) {
224 zink_gfx_program_remove_shader((void*)entry->key, shader);
225 }
226 _mesa_set_destroy(shader->programs, NULL);
227 FREE(shader);
228 }