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 #ifndef ZINK_PROGRAM_H
25 #define ZINK_PROGRAM_H
26
27 #include <vulkan/vulkan.h>
28
29 #include "compiler/shader_enums.h"
30 #include "pipe/p_state.h"
31 #include "util/u_inlines.h"
32
33 #include "zink_context.h"
34 #include "zink_compiler.h"
35 #include "zink_shader_keys.h"
36 #ifdef __cplusplus
37 extern "C" {
38 #endif
39
40 struct zink_screen;
41 struct zink_shader;
42 struct zink_gfx_pipeline_state;
43 struct zink_descriptor_set;
44
45 struct hash_table;
46 struct set;
47 struct util_dynarray;
48
49 struct zink_program;
50
51 struct zink_gfx_push_constant {
52 unsigned draw_mode_is_indexed;
53 unsigned draw_id;
54 float default_inner_level[2];
55 float default_outer_level[4];
56 };
57
58 struct zink_cs_push_constant {
59 unsigned work_dim;
60 };
61
62 /* a shader module is used for directly reusing a shader module between programs,
63 * e.g., in the case where we're swapping out only one shader,
64 * allowing us to skip going through shader keys
65 */
66 struct zink_shader_module {
67 struct list_head list;
68 VkShaderModule shader;
69 uint32_t hash;
70 bool default_variant;
71 bool has_nonseamless;
72 uint8_t num_uniforms;
73 uint8_t key_size;
74 uint8_t key[0]; /* | key | uniforms | */
75 };
76
77 struct zink_program {
78 struct pipe_reference reference;
79 unsigned char sha1[20];
80 struct util_queue_fence cache_fence;
81 VkPipelineCache pipeline_cache;
82 size_t pipeline_cache_size;
83 struct zink_batch_usage *batch_uses;
84 bool is_compute;
85
86 struct zink_program_descriptor_data *dd;
87
88 uint32_t compat_id;
89 VkPipelineLayout layout;
90 VkDescriptorSetLayout dsl[ZINK_DESCRIPTOR_TYPES + 2]; // one for each type + push + bindless
91 unsigned num_dsl;
92
93 bool removed;
94 };
95
96 #define ZINK_MAX_INLINED_VARIANTS 5
97
98 struct zink_gfx_program {
99 struct zink_program base;
100
101 uint32_t stages_present; //mask of stages present in this program
102 struct nir_shader *nir[ZINK_SHADER_COUNT];
103
104 struct zink_shader_module *modules[ZINK_SHADER_COUNT]; // compute stage doesn't belong here
105
106 struct zink_shader *last_vertex_stage;
107
108 struct list_head shader_cache[ZINK_SHADER_COUNT][2][2]; //normal, nonseamless cubes, inline uniforms
109 unsigned inlined_variant_count[ZINK_SHADER_COUNT];
110
111 struct zink_shader *shaders[ZINK_SHADER_COUNT];
112 struct hash_table pipelines[11]; // number of draw modes we support
113 uint32_t default_variant_hash;
114 uint32_t last_variant_hash;
115 };
116
117 struct zink_compute_program {
118 struct zink_program base;
119
120 struct zink_shader_module *curr;
121
122 struct zink_shader_module *module; //base
123 struct list_head shader_cache[2]; //nonseamless cubes, inline uniforms
124 unsigned inlined_variant_count;
125
126 struct zink_shader *shader;
127 struct hash_table *pipelines;
128 };
129
130 static inline enum zink_descriptor_type
zink_desc_type_from_vktype(VkDescriptorType type)131 zink_desc_type_from_vktype(VkDescriptorType type)
132 {
133 switch (type) {
134 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
135 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
136 return ZINK_DESCRIPTOR_TYPE_UBO;
137 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
138 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
139 return ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW;
140 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
141 return ZINK_DESCRIPTOR_TYPE_SSBO;
142 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
143 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
144 return ZINK_DESCRIPTOR_TYPE_IMAGE;
145 default:
146 unreachable("unhandled descriptor type");
147 }
148 }
149
150 static inline VkPrimitiveTopology
zink_primitive_topology(enum pipe_prim_type mode)151 zink_primitive_topology(enum pipe_prim_type mode)
152 {
153 switch (mode) {
154 case PIPE_PRIM_POINTS:
155 return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
156
157 case PIPE_PRIM_LINES:
158 return VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
159
160 case PIPE_PRIM_LINE_STRIP:
161 return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
162
163 case PIPE_PRIM_TRIANGLES:
164 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
165
166 case PIPE_PRIM_TRIANGLE_STRIP:
167 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
168
169 case PIPE_PRIM_TRIANGLE_FAN:
170 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN;
171
172 case PIPE_PRIM_LINE_STRIP_ADJACENCY:
173 return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY;
174
175 case PIPE_PRIM_LINES_ADJACENCY:
176 return VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY;
177
178 case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
179 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY;
180
181 case PIPE_PRIM_TRIANGLES_ADJACENCY:
182 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY;
183
184 case PIPE_PRIM_PATCHES:
185 return VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
186
187 default:
188 unreachable("unexpected enum pipe_prim_type");
189 }
190 }
191
192 void
193 zink_delete_shader_state(struct pipe_context *pctx, void *cso);
194 void *
195 zink_create_gfx_shader_state(struct pipe_context *pctx, const struct pipe_shader_state *shader);
196
197 unsigned
198 zink_program_num_bindings_typed(const struct zink_program *pg, enum zink_descriptor_type type, bool is_compute);
199
200 unsigned
201 zink_program_num_bindings(const struct zink_program *pg, bool is_compute);
202
203 bool
204 zink_program_descriptor_is_buffer(struct zink_context *ctx, enum pipe_shader_type stage, enum zink_descriptor_type type, unsigned i);
205
206 void
207 zink_update_gfx_program(struct zink_context *ctx, struct zink_gfx_program *prog);
208
209 struct zink_gfx_program *
210 zink_create_gfx_program(struct zink_context *ctx,
211 struct zink_shader *stages[ZINK_SHADER_COUNT],
212 unsigned vertices_per_patch);
213
214 void
215 zink_destroy_gfx_program(struct zink_context *ctx,
216 struct zink_gfx_program *prog);
217
218 VkPipeline
219 zink_get_gfx_pipeline(struct zink_context *ctx,
220 struct zink_gfx_program *prog,
221 struct zink_gfx_pipeline_state *state,
222 enum pipe_prim_type mode);
223
224 void
225 zink_program_init(struct zink_context *ctx);
226
227 uint32_t
228 zink_program_get_descriptor_usage(struct zink_context *ctx, enum pipe_shader_type stage, enum zink_descriptor_type type);
229
230 void
231 debug_describe_zink_gfx_program(char* buf, const struct zink_gfx_program *ptr);
232
233 static inline bool
zink_gfx_program_reference(struct zink_context * ctx,struct zink_gfx_program ** dst,struct zink_gfx_program * src)234 zink_gfx_program_reference(struct zink_context *ctx,
235 struct zink_gfx_program **dst,
236 struct zink_gfx_program *src)
237 {
238 struct zink_gfx_program *old_dst = dst ? *dst : NULL;
239 bool ret = false;
240
241 if (pipe_reference_described(old_dst ? &old_dst->base.reference : NULL, &src->base.reference,
242 (debug_reference_descriptor)debug_describe_zink_gfx_program)) {
243 zink_destroy_gfx_program(ctx, old_dst);
244 ret = true;
245 }
246 if (dst) *dst = src;
247 return ret;
248 }
249
250 struct zink_compute_program *
251 zink_create_compute_program(struct zink_context *ctx, struct zink_shader *shader);
252 void
253 zink_destroy_compute_program(struct zink_context *ctx,
254 struct zink_compute_program *comp);
255
256 void
257 debug_describe_zink_compute_program(char* buf, const struct zink_compute_program *ptr);
258
259 static inline bool
zink_compute_program_reference(struct zink_context * ctx,struct zink_compute_program ** dst,struct zink_compute_program * src)260 zink_compute_program_reference(struct zink_context *ctx,
261 struct zink_compute_program **dst,
262 struct zink_compute_program *src)
263 {
264 struct zink_compute_program *old_dst = dst ? *dst : NULL;
265 bool ret = false;
266
267 if (pipe_reference_described(old_dst ? &old_dst->base.reference : NULL, &src->base.reference,
268 (debug_reference_descriptor)debug_describe_zink_compute_program)) {
269 zink_destroy_compute_program(ctx, old_dst);
270 ret = true;
271 }
272 if (dst) *dst = src;
273 return ret;
274 }
275
276 static inline bool
zink_program_reference(struct zink_context * ctx,struct zink_program ** dst,struct zink_program * src)277 zink_program_reference(struct zink_context *ctx,
278 struct zink_program **dst,
279 struct zink_program *src)
280 {
281 struct zink_program *pg = src ? src : dst ? *dst : NULL;
282 if (!pg)
283 return false;
284 if (pg->is_compute) {
285 struct zink_compute_program *comp = (struct zink_compute_program*)pg;
286 return zink_compute_program_reference(ctx, &comp, NULL);
287 } else {
288 struct zink_gfx_program *prog = (struct zink_gfx_program*)pg;
289 return zink_gfx_program_reference(ctx, &prog, NULL);
290 }
291 }
292
293 VkPipelineLayout
294 zink_pipeline_layout_create(struct zink_screen *screen, struct zink_program *pg, uint32_t *compat);
295
296 void
297 zink_program_update_compute_pipeline_state(struct zink_context *ctx, struct zink_compute_program *comp, const uint block[3]);
298 void
299 zink_update_compute_program(struct zink_context *ctx);
300 VkPipeline
301 zink_get_compute_pipeline(struct zink_screen *screen,
302 struct zink_compute_program *comp,
303 struct zink_compute_pipeline_state *state);
304
305 static inline bool
zink_program_has_descriptors(const struct zink_program * pg)306 zink_program_has_descriptors(const struct zink_program *pg)
307 {
308 return pg->num_dsl > 0;
309 }
310
311 static inline struct zink_fs_key *
zink_set_fs_key(struct zink_context * ctx)312 zink_set_fs_key(struct zink_context *ctx)
313 {
314 ctx->dirty_shader_stages |= BITFIELD_BIT(PIPE_SHADER_FRAGMENT);
315 return (struct zink_fs_key *)&ctx->gfx_pipeline_state.shader_keys.key[PIPE_SHADER_FRAGMENT];
316 }
317
318 static inline const struct zink_fs_key *
zink_get_fs_key(struct zink_context * ctx)319 zink_get_fs_key(struct zink_context *ctx)
320 {
321 return (const struct zink_fs_key *)&ctx->gfx_pipeline_state.shader_keys.key[PIPE_SHADER_FRAGMENT];
322 }
323
324 static inline bool
zink_set_tcs_key_patches(struct zink_context * ctx,uint8_t patch_vertices)325 zink_set_tcs_key_patches(struct zink_context *ctx, uint8_t patch_vertices)
326 {
327 struct zink_tcs_key *tcs = (struct zink_tcs_key*)&ctx->gfx_pipeline_state.shader_keys.key[PIPE_SHADER_TESS_CTRL];
328 if (tcs->patch_vertices == patch_vertices)
329 return false;
330 ctx->dirty_shader_stages |= BITFIELD_BIT(PIPE_SHADER_TESS_CTRL);
331 tcs->patch_vertices = patch_vertices;
332 return true;
333 }
334
335 static inline const struct zink_tcs_key *
zink_get_tcs_key(struct zink_context * ctx)336 zink_get_tcs_key(struct zink_context *ctx)
337 {
338 return (const struct zink_tcs_key *)&ctx->gfx_pipeline_state.shader_keys.key[PIPE_SHADER_TESS_CTRL];
339 }
340
341 void
342 zink_update_fs_key_samples(struct zink_context *ctx);
343
344 static inline struct zink_vs_key *
zink_set_vs_key(struct zink_context * ctx)345 zink_set_vs_key(struct zink_context *ctx)
346 {
347 ctx->dirty_shader_stages |= BITFIELD_BIT(PIPE_SHADER_VERTEX);
348 return (struct zink_vs_key *)&ctx->gfx_pipeline_state.shader_keys.key[PIPE_SHADER_VERTEX];
349 }
350
351 static inline const struct zink_vs_key *
zink_get_vs_key(struct zink_context * ctx)352 zink_get_vs_key(struct zink_context *ctx)
353 {
354 return (const struct zink_vs_key *)&ctx->gfx_pipeline_state.shader_keys.key[PIPE_SHADER_VERTEX];
355 }
356
357 static inline struct zink_vs_key_base *
zink_set_last_vertex_key(struct zink_context * ctx)358 zink_set_last_vertex_key(struct zink_context *ctx)
359 {
360 ctx->last_vertex_stage_dirty = true;
361 return (struct zink_vs_key_base *)&ctx->gfx_pipeline_state.shader_keys.last_vertex;
362 }
363
364 static inline const struct zink_vs_key_base *
zink_get_last_vertex_key(struct zink_context * ctx)365 zink_get_last_vertex_key(struct zink_context *ctx)
366 {
367 return (const struct zink_vs_key_base *)&ctx->gfx_pipeline_state.shader_keys.last_vertex;
368 }
369
370 static inline void
zink_set_fs_point_coord_key(struct zink_context * ctx)371 zink_set_fs_point_coord_key(struct zink_context *ctx)
372 {
373 const struct zink_fs_key *fs = zink_get_fs_key(ctx);
374 bool disable = !ctx->gfx_pipeline_state.has_points || !ctx->rast_state->base.sprite_coord_enable;
375 uint8_t coord_replace_bits = disable ? 0 : ctx->rast_state->base.sprite_coord_enable;
376 bool coord_replace_yinvert = disable ? false : !!ctx->rast_state->base.sprite_coord_mode;
377 if (fs->coord_replace_bits != coord_replace_bits || fs->coord_replace_yinvert != coord_replace_yinvert) {
378 zink_set_fs_key(ctx)->coord_replace_bits = coord_replace_bits;
379 zink_set_fs_key(ctx)->coord_replace_yinvert = coord_replace_yinvert;
380 }
381 }
382
383 bool
384 zink_set_rasterizer_discard(struct zink_context *ctx, bool disable);
385
386 #ifdef __cplusplus
387 }
388 #endif
389
390 #endif
391