f6b3acdc84d20cab17b5a68e6bb64f5c69d929c8
[mesa.git] / src / gallium / drivers / zink / zink_program.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_program.h"
25
26 #include "zink_compiler.h"
27 #include "zink_context.h"
28 #include "zink_render_pass.h"
29 #include "zink_screen.h"
30
31 #include "util/hash_table.h"
32 #include "util/set.h"
33 #include "util/u_debug.h"
34 #include "util/u_memory.h"
35 #include "tgsi/tgsi_from_mesa.h"
36
37 struct pipeline_cache_entry {
38 struct zink_gfx_pipeline_state state;
39 VkPipeline pipeline;
40 };
41
42 void
43 debug_describe_zink_gfx_program(char *buf, const struct zink_gfx_program *ptr)
44 {
45 sprintf(buf, "zink_gfx_program");
46 }
47
48 static void
49 debug_describe_zink_shader_module(char *buf, const struct zink_shader_module *ptr)
50 {
51 sprintf(buf, "zink_shader_module");
52 }
53
54 static VkDescriptorSetLayout
55 create_desc_set_layout(VkDevice dev,
56 struct zink_shader *stages[ZINK_SHADER_COUNT],
57 unsigned *num_descriptors)
58 {
59 VkDescriptorSetLayoutBinding bindings[PIPE_SHADER_TYPES * PIPE_MAX_CONSTANT_BUFFERS];
60 int num_bindings = 0;
61
62 for (int i = 0; i < ZINK_SHADER_COUNT; i++) {
63 struct zink_shader *shader = stages[i];
64 if (!shader)
65 continue;
66
67 VkShaderStageFlagBits stage_flags = zink_shader_stage(i);
68 for (int j = 0; j < shader->num_bindings; j++) {
69 assert(num_bindings < ARRAY_SIZE(bindings));
70 bindings[num_bindings].binding = shader->bindings[j].binding;
71 bindings[num_bindings].descriptorType = shader->bindings[j].type;
72 bindings[num_bindings].descriptorCount = 1;
73 bindings[num_bindings].stageFlags = stage_flags;
74 bindings[num_bindings].pImmutableSamplers = NULL;
75 ++num_bindings;
76 }
77 }
78
79 VkDescriptorSetLayoutCreateInfo dcslci = {};
80 dcslci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
81 dcslci.pNext = NULL;
82 dcslci.flags = 0;
83 dcslci.bindingCount = num_bindings;
84 dcslci.pBindings = bindings;
85
86 VkDescriptorSetLayout dsl;
87 if (vkCreateDescriptorSetLayout(dev, &dcslci, 0, &dsl) != VK_SUCCESS) {
88 debug_printf("vkCreateDescriptorSetLayout failed\n");
89 return VK_NULL_HANDLE;
90 }
91
92 *num_descriptors = num_bindings;
93 return dsl;
94 }
95
96 static VkPipelineLayout
97 create_pipeline_layout(VkDevice dev, VkDescriptorSetLayout dsl)
98 {
99 assert(dsl != VK_NULL_HANDLE);
100
101 VkPipelineLayoutCreateInfo plci = {};
102 plci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
103
104 plci.pSetLayouts = &dsl;
105 plci.setLayoutCount = 1;
106
107 VkPipelineLayout layout;
108 if (vkCreatePipelineLayout(dev, &plci, NULL, &layout) != VK_SUCCESS) {
109 debug_printf("vkCreatePipelineLayout failed!\n");
110 return VK_NULL_HANDLE;
111 }
112
113 return layout;
114 }
115
116 static void
117 zink_destroy_shader_module(struct zink_screen *screen, struct zink_shader_module *zm)
118 {
119 vkDestroyShaderModule(screen->dev, zm->shader, NULL);
120 free(zm);
121 }
122
123 static inline void
124 zink_shader_module_reference(struct zink_screen *screen,
125 struct zink_shader_module **dst,
126 struct zink_shader_module *src)
127 {
128 struct zink_shader_module *old_dst = dst ? *dst : NULL;
129
130 if (pipe_reference_described(old_dst ? &old_dst->reference : NULL, &src->reference,
131 (debug_reference_descriptor)debug_describe_zink_shader_module))
132 zink_destroy_shader_module(screen, old_dst);
133 if (dst) *dst = src;
134 }
135
136 static void
137 update_shader_modules(struct zink_context *ctx, struct zink_shader *stages[ZINK_SHADER_COUNT], struct zink_gfx_program *prog)
138 {
139 struct zink_shader *dirty[ZINK_SHADER_COUNT] = {NULL};
140
141 unsigned dirty_shader_stages = ctx->dirty_shader_stages;
142 while (dirty_shader_stages) {
143 unsigned type = u_bit_scan(&dirty_shader_stages);
144 dirty[type] = stages[type];
145 }
146 for (int i = 0; i < ZINK_SHADER_COUNT; ++i) {
147 if (dirty[i]) {
148 prog->stages[i] = CALLOC_STRUCT(zink_shader_module);
149 assert(prog->stages[i]);
150 pipe_reference_init(&prog->stages[i]->reference, 1);
151 prog->stages[i]->shader = zink_shader_compile(zink_screen(ctx->base.screen), stages[i]);
152 } else if (stages[i]) /* reuse existing shader module */
153 zink_shader_module_reference(zink_screen(ctx->base.screen), &prog->stages[i], ctx->curr_program->stages[i]);
154 prog->shaders[i] = stages[i];
155 }
156 ctx->dirty_shader_stages = 0;
157 }
158
159 static uint32_t
160 hash_gfx_pipeline_state(const void *key)
161 {
162 return _mesa_hash_data(key, sizeof(struct zink_gfx_pipeline_state));
163 }
164
165 static bool
166 equals_gfx_pipeline_state(const void *a, const void *b)
167 {
168 return memcmp(a, b, sizeof(struct zink_gfx_pipeline_state)) == 0;
169 }
170
171 struct zink_gfx_program *
172 zink_create_gfx_program(struct zink_context *ctx,
173 struct zink_shader *stages[ZINK_SHADER_COUNT])
174 {
175 struct zink_screen *screen = zink_screen(ctx->base.screen);
176 struct zink_gfx_program *prog = CALLOC_STRUCT(zink_gfx_program);
177 if (!prog)
178 goto fail;
179
180 pipe_reference_init(&prog->reference, 1);
181
182 update_shader_modules(ctx, stages, prog);
183
184 for (int i = 0; i < ARRAY_SIZE(prog->pipelines); ++i) {
185 prog->pipelines[i] = _mesa_hash_table_create(NULL,
186 hash_gfx_pipeline_state,
187 equals_gfx_pipeline_state);
188 if (!prog->pipelines[i])
189 goto fail;
190 }
191
192 for (int i = 0; i < ZINK_SHADER_COUNT; ++i) {
193 if (prog->stages[i]) {
194 _mesa_set_add(stages[i]->programs, prog);
195 zink_gfx_program_reference(screen, NULL, prog);
196 }
197 }
198
199 prog->dsl = create_desc_set_layout(screen->dev, stages,
200 &prog->num_descriptors);
201 if (!prog->dsl)
202 goto fail;
203
204 prog->layout = create_pipeline_layout(screen->dev, prog->dsl);
205 if (!prog->layout)
206 goto fail;
207
208 prog->render_passes = _mesa_set_create(NULL, _mesa_hash_pointer,
209 _mesa_key_pointer_equal);
210 if (!prog->render_passes)
211 goto fail;
212
213 return prog;
214
215 fail:
216 if (prog)
217 zink_destroy_gfx_program(screen, prog);
218 return NULL;
219 }
220
221 static void
222 gfx_program_remove_shader(struct zink_gfx_program *prog, struct zink_shader *shader)
223 {
224 enum pipe_shader_type p_stage = pipe_shader_type_from_mesa(shader->nir->info.stage);
225
226 assert(prog->shaders[p_stage] == shader);
227 prog->shaders[p_stage] = NULL;
228 _mesa_set_remove_key(shader->programs, prog);
229 }
230
231 void
232 zink_destroy_gfx_program(struct zink_screen *screen,
233 struct zink_gfx_program *prog)
234 {
235 if (prog->layout)
236 vkDestroyPipelineLayout(screen->dev, prog->layout, NULL);
237
238 if (prog->dsl)
239 vkDestroyDescriptorSetLayout(screen->dev, prog->dsl, NULL);
240
241 for (int i = 0; i < ZINK_SHADER_COUNT; ++i) {
242 if (prog->shaders[i])
243 gfx_program_remove_shader(prog, prog->shaders[i]);
244 if (prog->stages[i])
245 zink_shader_module_reference(screen, &prog->stages[i], NULL);
246 }
247
248 /* unref all used render-passes */
249 if (prog->render_passes) {
250 set_foreach(prog->render_passes, entry) {
251 struct zink_render_pass *pres = (struct zink_render_pass *)entry->key;
252 zink_render_pass_reference(screen, &pres, NULL);
253 }
254 _mesa_set_destroy(prog->render_passes, NULL);
255 }
256
257 for (int i = 0; i < ARRAY_SIZE(prog->pipelines); ++i) {
258 hash_table_foreach(prog->pipelines[i], entry) {
259 struct pipeline_cache_entry *pc_entry = entry->data;
260
261 vkDestroyPipeline(screen->dev, pc_entry->pipeline, NULL);
262 free(pc_entry);
263 }
264 _mesa_hash_table_destroy(prog->pipelines[i], NULL);
265 }
266
267 FREE(prog);
268 }
269
270 static VkPrimitiveTopology
271 primitive_topology(enum pipe_prim_type mode)
272 {
273 switch (mode) {
274 case PIPE_PRIM_POINTS:
275 return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
276
277 case PIPE_PRIM_LINES:
278 return VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
279
280 case PIPE_PRIM_LINE_STRIP:
281 return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
282
283 case PIPE_PRIM_TRIANGLES:
284 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
285
286 case PIPE_PRIM_TRIANGLE_STRIP:
287 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
288
289 case PIPE_PRIM_TRIANGLE_FAN:
290 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN;
291
292 default:
293 unreachable("unexpected enum pipe_prim_type");
294 }
295 }
296
297 static void
298 reference_render_pass(struct zink_screen *screen,
299 struct zink_gfx_program *prog,
300 struct zink_render_pass *render_pass)
301 {
302 struct set_entry *entry = _mesa_set_search(prog->render_passes,
303 render_pass);
304 if (!entry) {
305 entry = _mesa_set_add(prog->render_passes, render_pass);
306 pipe_reference(NULL, &render_pass->reference);
307 }
308 }
309
310 VkPipeline
311 zink_get_gfx_pipeline(struct zink_screen *screen,
312 struct zink_gfx_program *prog,
313 struct zink_gfx_pipeline_state *state,
314 enum pipe_prim_type mode)
315 {
316 assert(mode <= ARRAY_SIZE(prog->pipelines));
317
318 /* TODO: use pre-hashed versions to save some time (can re-hash only when
319 state changes) */
320 struct hash_entry *entry = _mesa_hash_table_search(prog->pipelines[mode], state);
321 if (!entry) {
322 VkPrimitiveTopology vkmode = primitive_topology(mode);
323 VkPipeline pipeline = zink_create_gfx_pipeline(screen, prog,
324 state, vkmode);
325 if (pipeline == VK_NULL_HANDLE)
326 return VK_NULL_HANDLE;
327
328 struct pipeline_cache_entry *pc_entry = CALLOC_STRUCT(pipeline_cache_entry);
329 if (!pc_entry)
330 return VK_NULL_HANDLE;
331
332 memcpy(&pc_entry->state, state, sizeof(*state));
333 pc_entry->pipeline = pipeline;
334
335 entry = _mesa_hash_table_insert(prog->pipelines[mode], &pc_entry->state, pc_entry);
336 assert(entry);
337
338 reference_render_pass(screen, prog, state->render_pass);
339 }
340
341 return ((struct pipeline_cache_entry *)(entry->data))->pipeline;
342 }
343
344
345 static void *
346 zink_create_vs_state(struct pipe_context *pctx,
347 const struct pipe_shader_state *shader)
348 {
349 struct nir_shader *nir;
350 if (shader->type != PIPE_SHADER_IR_NIR)
351 nir = zink_tgsi_to_nir(pctx->screen, shader->tokens);
352 else
353 nir = (struct nir_shader *)shader->ir.nir;
354
355 return zink_shader_create(zink_screen(pctx->screen), nir, &shader->stream_output);
356 }
357
358 static void
359 bind_stage(struct zink_context *ctx, enum pipe_shader_type stage,
360 struct zink_shader *shader)
361 {
362 assert(stage < PIPE_SHADER_COMPUTE);
363 ctx->gfx_stages[stage] = shader;
364 ctx->dirty_shader_stages |= 1 << stage;
365 }
366
367 static void
368 zink_bind_vs_state(struct pipe_context *pctx,
369 void *cso)
370 {
371 bind_stage(zink_context(pctx), PIPE_SHADER_VERTEX, cso);
372 }
373
374 static void
375 zink_delete_vs_state(struct pipe_context *pctx,
376 void *cso)
377 {
378 zink_shader_free(zink_context(pctx), cso);
379 }
380
381 static void *
382 zink_create_fs_state(struct pipe_context *pctx,
383 const struct pipe_shader_state *shader)
384 {
385 struct nir_shader *nir;
386 if (shader->type != PIPE_SHADER_IR_NIR)
387 nir = zink_tgsi_to_nir(pctx->screen, shader->tokens);
388 else
389 nir = (struct nir_shader *)shader->ir.nir;
390
391 return zink_shader_create(zink_screen(pctx->screen), nir, NULL);
392 }
393
394 static void
395 zink_bind_fs_state(struct pipe_context *pctx,
396 void *cso)
397 {
398 bind_stage(zink_context(pctx), PIPE_SHADER_FRAGMENT, cso);
399 }
400
401 static void
402 zink_delete_fs_state(struct pipe_context *pctx,
403 void *cso)
404 {
405 zink_shader_free(zink_context(pctx), cso);
406 }
407
408
409 void
410 zink_program_init(struct zink_context *ctx)
411 {
412 ctx->base.create_vs_state = zink_create_vs_state;
413 ctx->base.bind_vs_state = zink_bind_vs_state;
414 ctx->base.delete_vs_state = zink_delete_vs_state;
415
416 ctx->base.create_fs_state = zink_create_fs_state;
417 ctx->base.bind_fs_state = zink_bind_fs_state;
418 ctx->base.delete_fs_state = zink_delete_fs_state;
419 }