• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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