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 37extern "C" { 38#endif 39 40struct zink_screen; 41struct zink_shader; 42struct zink_gfx_pipeline_state; 43struct zink_descriptor_set; 44 45struct hash_table; 46struct set; 47struct util_dynarray; 48 49struct zink_program; 50 51struct 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 58struct 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 */ 66struct 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 77struct 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 98struct 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 117struct 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 130static inline enum zink_descriptor_type 131zink_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 150static inline VkPrimitiveTopology 151zink_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 192void 193zink_delete_shader_state(struct pipe_context *pctx, void *cso); 194void * 195zink_create_gfx_shader_state(struct pipe_context *pctx, const struct pipe_shader_state *shader); 196 197unsigned 198zink_program_num_bindings_typed(const struct zink_program *pg, enum zink_descriptor_type type, bool is_compute); 199 200unsigned 201zink_program_num_bindings(const struct zink_program *pg, bool is_compute); 202 203bool 204zink_program_descriptor_is_buffer(struct zink_context *ctx, enum pipe_shader_type stage, enum zink_descriptor_type type, unsigned i); 205 206void 207zink_update_gfx_program(struct zink_context *ctx, struct zink_gfx_program *prog); 208 209struct zink_gfx_program * 210zink_create_gfx_program(struct zink_context *ctx, 211 struct zink_shader *stages[ZINK_SHADER_COUNT], 212 unsigned vertices_per_patch); 213 214void 215zink_destroy_gfx_program(struct zink_context *ctx, 216 struct zink_gfx_program *prog); 217 218VkPipeline 219zink_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 224void 225zink_program_init(struct zink_context *ctx); 226 227uint32_t 228zink_program_get_descriptor_usage(struct zink_context *ctx, enum pipe_shader_type stage, enum zink_descriptor_type type); 229 230void 231debug_describe_zink_gfx_program(char* buf, const struct zink_gfx_program *ptr); 232 233static inline bool 234zink_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 250struct zink_compute_program * 251zink_create_compute_program(struct zink_context *ctx, struct zink_shader *shader); 252void 253zink_destroy_compute_program(struct zink_context *ctx, 254 struct zink_compute_program *comp); 255 256void 257debug_describe_zink_compute_program(char* buf, const struct zink_compute_program *ptr); 258 259static inline bool 260zink_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 276static inline bool 277zink_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 293VkPipelineLayout 294zink_pipeline_layout_create(struct zink_screen *screen, struct zink_program *pg, uint32_t *compat); 295 296void 297zink_program_update_compute_pipeline_state(struct zink_context *ctx, struct zink_compute_program *comp, const uint block[3]); 298void 299zink_update_compute_program(struct zink_context *ctx); 300VkPipeline 301zink_get_compute_pipeline(struct zink_screen *screen, 302 struct zink_compute_program *comp, 303 struct zink_compute_pipeline_state *state); 304 305static inline bool 306zink_program_has_descriptors(const struct zink_program *pg) 307{ 308 return pg->num_dsl > 0; 309} 310 311static inline struct zink_fs_key * 312zink_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 318static inline const struct zink_fs_key * 319zink_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 324static inline bool 325zink_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 335static inline const struct zink_tcs_key * 336zink_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 341void 342zink_update_fs_key_samples(struct zink_context *ctx); 343 344static inline struct zink_vs_key * 345zink_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 351static inline const struct zink_vs_key * 352zink_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 357static inline struct zink_vs_key_base * 358zink_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 364static inline const struct zink_vs_key_base * 365zink_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 370static inline void 371zink_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 383bool 384zink_set_rasterizer_discard(struct zink_context *ctx, bool disable); 385 386#ifdef __cplusplus 387} 388#endif 389 390#endif 391