1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2018 Collabora Ltd. 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub 8bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom 9bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 19bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 21bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include "zink_program.h" 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_ci#include "zink_compiler.h" 27bf215546Sopenharmony_ci#include "zink_context.h" 28bf215546Sopenharmony_ci#include "zink_descriptors.h" 29bf215546Sopenharmony_ci#include "zink_helpers.h" 30bf215546Sopenharmony_ci#include "zink_render_pass.h" 31bf215546Sopenharmony_ci#include "zink_resource.h" 32bf215546Sopenharmony_ci#include "zink_screen.h" 33bf215546Sopenharmony_ci#include "zink_state.h" 34bf215546Sopenharmony_ci#include "zink_inlines.h" 35bf215546Sopenharmony_ci 36bf215546Sopenharmony_ci#include "util/hash_table.h" 37bf215546Sopenharmony_ci#include "util/set.h" 38bf215546Sopenharmony_ci#include "util/u_debug.h" 39bf215546Sopenharmony_ci#include "util/u_memory.h" 40bf215546Sopenharmony_ci#include "util/u_prim.h" 41bf215546Sopenharmony_ci#include "tgsi/tgsi_from_mesa.h" 42bf215546Sopenharmony_ci 43bf215546Sopenharmony_ci/* for pipeline cache */ 44bf215546Sopenharmony_ci#define XXH_INLINE_ALL 45bf215546Sopenharmony_ci#include "util/xxhash.h" 46bf215546Sopenharmony_ci 47bf215546Sopenharmony_cistruct gfx_pipeline_cache_entry { 48bf215546Sopenharmony_ci struct zink_gfx_pipeline_state state; 49bf215546Sopenharmony_ci VkPipeline pipeline; 50bf215546Sopenharmony_ci}; 51bf215546Sopenharmony_ci 52bf215546Sopenharmony_cistruct compute_pipeline_cache_entry { 53bf215546Sopenharmony_ci struct zink_compute_pipeline_state state; 54bf215546Sopenharmony_ci VkPipeline pipeline; 55bf215546Sopenharmony_ci}; 56bf215546Sopenharmony_ci 57bf215546Sopenharmony_civoid 58bf215546Sopenharmony_cidebug_describe_zink_gfx_program(char *buf, const struct zink_gfx_program *ptr) 59bf215546Sopenharmony_ci{ 60bf215546Sopenharmony_ci sprintf(buf, "zink_gfx_program"); 61bf215546Sopenharmony_ci} 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_civoid 64bf215546Sopenharmony_cidebug_describe_zink_compute_program(char *buf, const struct zink_compute_program *ptr) 65bf215546Sopenharmony_ci{ 66bf215546Sopenharmony_ci sprintf(buf, "zink_compute_program"); 67bf215546Sopenharmony_ci} 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_cistatic bool 70bf215546Sopenharmony_cishader_key_matches(const struct zink_shader_module *zm, bool ignore_size, 71bf215546Sopenharmony_ci const struct zink_shader_key *key, unsigned num_uniforms) 72bf215546Sopenharmony_ci{ 73bf215546Sopenharmony_ci bool key_size_differs = ignore_size ? false : zm->key_size != key->size; 74bf215546Sopenharmony_ci if (key_size_differs || zm->num_uniforms != num_uniforms || zm->has_nonseamless != !!key->base.nonseamless_cube_mask) 75bf215546Sopenharmony_ci return false; 76bf215546Sopenharmony_ci const uint32_t nonseamless_size = zm->has_nonseamless ? sizeof(uint32_t) : 0; 77bf215546Sopenharmony_ci return !memcmp(zm->key, key, zm->key_size) && 78bf215546Sopenharmony_ci (!nonseamless_size || !memcmp(zm->key + zm->key_size, &key->base.nonseamless_cube_mask, nonseamless_size)) && 79bf215546Sopenharmony_ci (!num_uniforms || !memcmp(zm->key + zm->key_size + nonseamless_size, 80bf215546Sopenharmony_ci key->base.inlined_uniform_values, zm->num_uniforms * sizeof(uint32_t))); 81bf215546Sopenharmony_ci} 82bf215546Sopenharmony_ci 83bf215546Sopenharmony_cistatic uint32_t 84bf215546Sopenharmony_cishader_module_hash(const struct zink_shader_module *zm) 85bf215546Sopenharmony_ci{ 86bf215546Sopenharmony_ci const uint32_t nonseamless_size = zm->has_nonseamless ? sizeof(uint32_t) : 0; 87bf215546Sopenharmony_ci unsigned key_size = zm->key_size + nonseamless_size + zm->num_uniforms * sizeof(uint32_t); 88bf215546Sopenharmony_ci return _mesa_hash_data(zm->key, key_size); 89bf215546Sopenharmony_ci} 90bf215546Sopenharmony_ci 91bf215546Sopenharmony_cistatic struct zink_shader_module * 92bf215546Sopenharmony_ciget_shader_module_for_stage(struct zink_context *ctx, struct zink_screen *screen, 93bf215546Sopenharmony_ci struct zink_shader *zs, struct zink_gfx_program *prog, 94bf215546Sopenharmony_ci struct zink_gfx_pipeline_state *state) 95bf215546Sopenharmony_ci{ 96bf215546Sopenharmony_ci gl_shader_stage stage = zs->nir->info.stage; 97bf215546Sopenharmony_ci enum pipe_shader_type pstage = pipe_shader_type_from_mesa(stage); 98bf215546Sopenharmony_ci VkShaderModule mod; 99bf215546Sopenharmony_ci struct zink_shader_module *zm = NULL; 100bf215546Sopenharmony_ci unsigned inline_size = 0, nonseamless_size = 0; 101bf215546Sopenharmony_ci struct zink_shader_key *key = &state->shader_keys.key[pstage]; 102bf215546Sopenharmony_ci bool ignore_key_size = false; 103bf215546Sopenharmony_ci if (pstage == PIPE_SHADER_TESS_CTRL && !zs->is_generated) { 104bf215546Sopenharmony_ci /* non-generated tcs won't use the shader key */ 105bf215546Sopenharmony_ci ignore_key_size = true; 106bf215546Sopenharmony_ci } 107bf215546Sopenharmony_ci if (ctx && zs->nir->info.num_inlinable_uniforms && 108bf215546Sopenharmony_ci ctx->inlinable_uniforms_valid_mask & BITFIELD64_BIT(pstage)) { 109bf215546Sopenharmony_ci if (zs->can_inline && (screen->is_cpu || prog->inlined_variant_count[pstage] < ZINK_MAX_INLINED_VARIANTS)) 110bf215546Sopenharmony_ci inline_size = zs->nir->info.num_inlinable_uniforms; 111bf215546Sopenharmony_ci else 112bf215546Sopenharmony_ci key->inline_uniforms = false; 113bf215546Sopenharmony_ci } 114bf215546Sopenharmony_ci if (key->base.nonseamless_cube_mask) 115bf215546Sopenharmony_ci nonseamless_size = sizeof(uint32_t); 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_ci struct zink_shader_module *iter, *next; 118bf215546Sopenharmony_ci LIST_FOR_EACH_ENTRY_SAFE(iter, next, &prog->shader_cache[pstage][!!nonseamless_size][!!inline_size], list) { 119bf215546Sopenharmony_ci if (!shader_key_matches(iter, ignore_key_size, key, inline_size)) 120bf215546Sopenharmony_ci continue; 121bf215546Sopenharmony_ci list_delinit(&iter->list); 122bf215546Sopenharmony_ci zm = iter; 123bf215546Sopenharmony_ci break; 124bf215546Sopenharmony_ci } 125bf215546Sopenharmony_ci 126bf215546Sopenharmony_ci if (!zm) { 127bf215546Sopenharmony_ci zm = malloc(sizeof(struct zink_shader_module) + key->size + nonseamless_size + inline_size * sizeof(uint32_t)); 128bf215546Sopenharmony_ci if (!zm) { 129bf215546Sopenharmony_ci return NULL; 130bf215546Sopenharmony_ci } 131bf215546Sopenharmony_ci unsigned patch_vertices = state->shader_keys.key[PIPE_SHADER_TESS_CTRL ].key.tcs.patch_vertices; 132bf215546Sopenharmony_ci if (pstage == PIPE_SHADER_TESS_CTRL && zs->is_generated && zs->spirv) { 133bf215546Sopenharmony_ci assert(ctx); //TODO async 134bf215546Sopenharmony_ci mod = zink_shader_tcs_compile(screen, zs, patch_vertices); 135bf215546Sopenharmony_ci } else { 136bf215546Sopenharmony_ci mod = zink_shader_compile(screen, zs, prog->nir[stage], key); 137bf215546Sopenharmony_ci } 138bf215546Sopenharmony_ci if (!mod) { 139bf215546Sopenharmony_ci FREE(zm); 140bf215546Sopenharmony_ci return NULL; 141bf215546Sopenharmony_ci } 142bf215546Sopenharmony_ci zm->shader = mod; 143bf215546Sopenharmony_ci list_inithead(&zm->list); 144bf215546Sopenharmony_ci zm->num_uniforms = inline_size; 145bf215546Sopenharmony_ci if (!ignore_key_size) { 146bf215546Sopenharmony_ci zm->key_size = key->size; 147bf215546Sopenharmony_ci memcpy(zm->key, key, key->size); 148bf215546Sopenharmony_ci } else { 149bf215546Sopenharmony_ci zm->key_size = 0; 150bf215546Sopenharmony_ci memset(zm->key, 0, key->size); 151bf215546Sopenharmony_ci } 152bf215546Sopenharmony_ci if (nonseamless_size) { 153bf215546Sopenharmony_ci /* nonseamless mask gets added to base key if it exists */ 154bf215546Sopenharmony_ci memcpy(zm->key + key->size, &key->base.nonseamless_cube_mask, nonseamless_size); 155bf215546Sopenharmony_ci } 156bf215546Sopenharmony_ci zm->has_nonseamless = !!nonseamless_size; 157bf215546Sopenharmony_ci if (inline_size) 158bf215546Sopenharmony_ci memcpy(zm->key + key->size + nonseamless_size, key->base.inlined_uniform_values, inline_size * sizeof(uint32_t)); 159bf215546Sopenharmony_ci if (pstage == PIPE_SHADER_TESS_CTRL && zs->is_generated) 160bf215546Sopenharmony_ci zm->hash = patch_vertices; 161bf215546Sopenharmony_ci else 162bf215546Sopenharmony_ci zm->hash = shader_module_hash(zm); 163bf215546Sopenharmony_ci zm->default_variant = !inline_size && list_is_empty(&prog->shader_cache[pstage][0][0]); 164bf215546Sopenharmony_ci if (inline_size) 165bf215546Sopenharmony_ci prog->inlined_variant_count[pstage]++; 166bf215546Sopenharmony_ci } 167bf215546Sopenharmony_ci list_add(&zm->list, &prog->shader_cache[pstage][!!nonseamless_size][!!inline_size]); 168bf215546Sopenharmony_ci return zm; 169bf215546Sopenharmony_ci} 170bf215546Sopenharmony_ci 171bf215546Sopenharmony_cistatic void 172bf215546Sopenharmony_cizink_destroy_shader_module(struct zink_screen *screen, struct zink_shader_module *zm) 173bf215546Sopenharmony_ci{ 174bf215546Sopenharmony_ci VKSCR(DestroyShaderModule)(screen->dev, zm->shader, NULL); 175bf215546Sopenharmony_ci free(zm); 176bf215546Sopenharmony_ci} 177bf215546Sopenharmony_ci 178bf215546Sopenharmony_cistatic void 179bf215546Sopenharmony_cidestroy_shader_cache(struct zink_screen *screen, struct list_head *sc) 180bf215546Sopenharmony_ci{ 181bf215546Sopenharmony_ci struct zink_shader_module *zm, *next; 182bf215546Sopenharmony_ci LIST_FOR_EACH_ENTRY_SAFE(zm, next, sc, list) { 183bf215546Sopenharmony_ci list_delinit(&zm->list); 184bf215546Sopenharmony_ci zink_destroy_shader_module(screen, zm); 185bf215546Sopenharmony_ci } 186bf215546Sopenharmony_ci} 187bf215546Sopenharmony_ci 188bf215546Sopenharmony_cistatic void 189bf215546Sopenharmony_ciupdate_gfx_shader_modules(struct zink_context *ctx, 190bf215546Sopenharmony_ci struct zink_screen *screen, 191bf215546Sopenharmony_ci struct zink_gfx_program *prog, uint32_t mask, 192bf215546Sopenharmony_ci struct zink_gfx_pipeline_state *state) 193bf215546Sopenharmony_ci{ 194bf215546Sopenharmony_ci bool hash_changed = false; 195bf215546Sopenharmony_ci bool default_variants = true; 196bf215546Sopenharmony_ci bool first = !prog->modules[PIPE_SHADER_VERTEX]; 197bf215546Sopenharmony_ci uint32_t variant_hash = prog->last_variant_hash; 198bf215546Sopenharmony_ci u_foreach_bit(pstage, mask) { 199bf215546Sopenharmony_ci assert(prog->shaders[pstage]); 200bf215546Sopenharmony_ci struct zink_shader_module *zm = get_shader_module_for_stage(ctx, screen, prog->shaders[pstage], prog, state); 201bf215546Sopenharmony_ci state->modules[pstage] = zm->shader; 202bf215546Sopenharmony_ci if (prog->modules[pstage] == zm) 203bf215546Sopenharmony_ci continue; 204bf215546Sopenharmony_ci if (prog->modules[pstage]) 205bf215546Sopenharmony_ci variant_hash ^= prog->modules[pstage]->hash; 206bf215546Sopenharmony_ci hash_changed = true; 207bf215546Sopenharmony_ci default_variants &= zm->default_variant; 208bf215546Sopenharmony_ci prog->modules[pstage] = zm; 209bf215546Sopenharmony_ci variant_hash ^= prog->modules[pstage]->hash; 210bf215546Sopenharmony_ci } 211bf215546Sopenharmony_ci 212bf215546Sopenharmony_ci if (hash_changed && state) { 213bf215546Sopenharmony_ci if (default_variants && !first) 214bf215546Sopenharmony_ci prog->last_variant_hash = prog->default_variant_hash; 215bf215546Sopenharmony_ci else { 216bf215546Sopenharmony_ci prog->last_variant_hash = variant_hash; 217bf215546Sopenharmony_ci if (first) { 218bf215546Sopenharmony_ci p_atomic_dec(&prog->base.reference.count); 219bf215546Sopenharmony_ci prog->default_variant_hash = prog->last_variant_hash; 220bf215546Sopenharmony_ci } 221bf215546Sopenharmony_ci } 222bf215546Sopenharmony_ci 223bf215546Sopenharmony_ci state->modules_changed = true; 224bf215546Sopenharmony_ci } 225bf215546Sopenharmony_ci} 226bf215546Sopenharmony_ci 227bf215546Sopenharmony_cistatic uint32_t 228bf215546Sopenharmony_cihash_gfx_pipeline_state(const void *key) 229bf215546Sopenharmony_ci{ 230bf215546Sopenharmony_ci const struct zink_gfx_pipeline_state *state = key; 231bf215546Sopenharmony_ci uint32_t hash = _mesa_hash_data(key, offsetof(struct zink_gfx_pipeline_state, hash)); 232bf215546Sopenharmony_ci if (!state->have_EXT_extended_dynamic_state2) 233bf215546Sopenharmony_ci hash = XXH32(&state->dyn_state2, sizeof(state->dyn_state2), hash); 234bf215546Sopenharmony_ci if (state->have_EXT_extended_dynamic_state) 235bf215546Sopenharmony_ci return hash; 236bf215546Sopenharmony_ci return XXH32(&state->dyn_state1, sizeof(state->dyn_state1), hash); 237bf215546Sopenharmony_ci} 238bf215546Sopenharmony_ci 239bf215546Sopenharmony_cistatic bool 240bf215546Sopenharmony_ciequals_gfx_pipeline_state(const void *a, const void *b) 241bf215546Sopenharmony_ci{ 242bf215546Sopenharmony_ci const struct zink_gfx_pipeline_state *sa = a; 243bf215546Sopenharmony_ci const struct zink_gfx_pipeline_state *sb = b; 244bf215546Sopenharmony_ci if (sa->uses_dynamic_stride != sb->uses_dynamic_stride) 245bf215546Sopenharmony_ci return false; 246bf215546Sopenharmony_ci /* dynamic vs rp */ 247bf215546Sopenharmony_ci if (!!sa->render_pass != !!sb->render_pass) 248bf215546Sopenharmony_ci return false; 249bf215546Sopenharmony_ci if (!sa->have_EXT_extended_dynamic_state || !sa->uses_dynamic_stride) { 250bf215546Sopenharmony_ci if (sa->vertex_buffers_enabled_mask != sb->vertex_buffers_enabled_mask) 251bf215546Sopenharmony_ci return false; 252bf215546Sopenharmony_ci /* if we don't have dynamic states, we have to hash the enabled vertex buffer bindings */ 253bf215546Sopenharmony_ci uint32_t mask_a = sa->vertex_buffers_enabled_mask; 254bf215546Sopenharmony_ci uint32_t mask_b = sb->vertex_buffers_enabled_mask; 255bf215546Sopenharmony_ci while (mask_a || mask_b) { 256bf215546Sopenharmony_ci unsigned idx_a = u_bit_scan(&mask_a); 257bf215546Sopenharmony_ci unsigned idx_b = u_bit_scan(&mask_b); 258bf215546Sopenharmony_ci if (sa->vertex_strides[idx_a] != sb->vertex_strides[idx_b]) 259bf215546Sopenharmony_ci return false; 260bf215546Sopenharmony_ci } 261bf215546Sopenharmony_ci } 262bf215546Sopenharmony_ci if (!sa->have_EXT_extended_dynamic_state) { 263bf215546Sopenharmony_ci if (memcmp(&sa->dyn_state1, &sb->dyn_state1, offsetof(struct zink_pipeline_dynamic_state1, depth_stencil_alpha_state))) 264bf215546Sopenharmony_ci return false; 265bf215546Sopenharmony_ci if (!!sa->dyn_state1.depth_stencil_alpha_state != !!sb->dyn_state1.depth_stencil_alpha_state || 266bf215546Sopenharmony_ci (sa->dyn_state1.depth_stencil_alpha_state && 267bf215546Sopenharmony_ci memcmp(sa->dyn_state1.depth_stencil_alpha_state, sb->dyn_state1.depth_stencil_alpha_state, 268bf215546Sopenharmony_ci sizeof(struct zink_depth_stencil_alpha_hw_state)))) 269bf215546Sopenharmony_ci return false; 270bf215546Sopenharmony_ci } 271bf215546Sopenharmony_ci if (!sa->have_EXT_extended_dynamic_state2) { 272bf215546Sopenharmony_ci if (memcmp(&sa->dyn_state2, &sb->dyn_state2, sizeof(sa->dyn_state2))) 273bf215546Sopenharmony_ci return false; 274bf215546Sopenharmony_ci } else if (!sa->extendedDynamicState2PatchControlPoints) { 275bf215546Sopenharmony_ci if (sa->dyn_state2.vertices_per_patch != sb->dyn_state2.vertices_per_patch) 276bf215546Sopenharmony_ci return false; 277bf215546Sopenharmony_ci } 278bf215546Sopenharmony_ci return !memcmp(sa->modules, sb->modules, sizeof(sa->modules)) && 279bf215546Sopenharmony_ci !memcmp(a, b, offsetof(struct zink_gfx_pipeline_state, hash)); 280bf215546Sopenharmony_ci} 281bf215546Sopenharmony_ci 282bf215546Sopenharmony_civoid 283bf215546Sopenharmony_cizink_update_gfx_program(struct zink_context *ctx, struct zink_gfx_program *prog) 284bf215546Sopenharmony_ci{ 285bf215546Sopenharmony_ci update_gfx_shader_modules(ctx, zink_screen(ctx->base.screen), prog, ctx->dirty_shader_stages & prog->stages_present, &ctx->gfx_pipeline_state); 286bf215546Sopenharmony_ci} 287bf215546Sopenharmony_ci 288bf215546Sopenharmony_cistatic void 289bf215546Sopenharmony_ciupdate_cs_shader_module(struct zink_context *ctx, struct zink_compute_program *comp) 290bf215546Sopenharmony_ci{ 291bf215546Sopenharmony_ci struct zink_screen *screen = zink_screen(ctx->base.screen); 292bf215546Sopenharmony_ci struct zink_shader *zs = comp->shader; 293bf215546Sopenharmony_ci VkShaderModule mod; 294bf215546Sopenharmony_ci struct zink_shader_module *zm = NULL; 295bf215546Sopenharmony_ci unsigned inline_size = 0, nonseamless_size = 0; 296bf215546Sopenharmony_ci struct zink_shader_key *key = &ctx->compute_pipeline_state.key; 297bf215546Sopenharmony_ci 298bf215546Sopenharmony_ci if (ctx && zs->nir->info.num_inlinable_uniforms && 299bf215546Sopenharmony_ci ctx->inlinable_uniforms_valid_mask & BITFIELD64_BIT(PIPE_SHADER_COMPUTE)) { 300bf215546Sopenharmony_ci if (screen->is_cpu || comp->inlined_variant_count < ZINK_MAX_INLINED_VARIANTS) 301bf215546Sopenharmony_ci inline_size = zs->nir->info.num_inlinable_uniforms; 302bf215546Sopenharmony_ci else 303bf215546Sopenharmony_ci key->inline_uniforms = false; 304bf215546Sopenharmony_ci } 305bf215546Sopenharmony_ci if (key->base.nonseamless_cube_mask) 306bf215546Sopenharmony_ci nonseamless_size = sizeof(uint32_t); 307bf215546Sopenharmony_ci 308bf215546Sopenharmony_ci if (inline_size || nonseamless_size) { 309bf215546Sopenharmony_ci struct zink_shader_module *iter, *next; 310bf215546Sopenharmony_ci LIST_FOR_EACH_ENTRY_SAFE(iter, next, &comp->shader_cache[!!nonseamless_size], list) { 311bf215546Sopenharmony_ci if (!shader_key_matches(iter, false, key, inline_size)) 312bf215546Sopenharmony_ci continue; 313bf215546Sopenharmony_ci list_delinit(&iter->list); 314bf215546Sopenharmony_ci zm = iter; 315bf215546Sopenharmony_ci break; 316bf215546Sopenharmony_ci } 317bf215546Sopenharmony_ci } else { 318bf215546Sopenharmony_ci zm = comp->module; 319bf215546Sopenharmony_ci } 320bf215546Sopenharmony_ci 321bf215546Sopenharmony_ci if (!zm) { 322bf215546Sopenharmony_ci zm = malloc(sizeof(struct zink_shader_module) + nonseamless_size + inline_size * sizeof(uint32_t)); 323bf215546Sopenharmony_ci if (!zm) { 324bf215546Sopenharmony_ci return; 325bf215546Sopenharmony_ci } 326bf215546Sopenharmony_ci mod = zink_shader_compile(screen, zs, comp->shader->nir, key); 327bf215546Sopenharmony_ci if (!mod) { 328bf215546Sopenharmony_ci FREE(zm); 329bf215546Sopenharmony_ci return; 330bf215546Sopenharmony_ci } 331bf215546Sopenharmony_ci zm->shader = mod; 332bf215546Sopenharmony_ci list_inithead(&zm->list); 333bf215546Sopenharmony_ci zm->num_uniforms = inline_size; 334bf215546Sopenharmony_ci zm->key_size = 0; 335bf215546Sopenharmony_ci zm->has_nonseamless = !!nonseamless_size; 336bf215546Sopenharmony_ci assert(nonseamless_size || inline_size); 337bf215546Sopenharmony_ci if (nonseamless_size) 338bf215546Sopenharmony_ci memcpy(zm->key, &key->base.nonseamless_cube_mask, nonseamless_size); 339bf215546Sopenharmony_ci if (inline_size) 340bf215546Sopenharmony_ci memcpy(zm->key + nonseamless_size, key->base.inlined_uniform_values, inline_size * sizeof(uint32_t)); 341bf215546Sopenharmony_ci zm->hash = shader_module_hash(zm); 342bf215546Sopenharmony_ci zm->default_variant = false; 343bf215546Sopenharmony_ci if (inline_size) 344bf215546Sopenharmony_ci comp->inlined_variant_count++; 345bf215546Sopenharmony_ci } 346bf215546Sopenharmony_ci if (zm->num_uniforms || nonseamless_size) 347bf215546Sopenharmony_ci list_add(&zm->list, &comp->shader_cache[!!nonseamless_size]); 348bf215546Sopenharmony_ci if (comp->curr == zm) 349bf215546Sopenharmony_ci return; 350bf215546Sopenharmony_ci ctx->compute_pipeline_state.final_hash ^= ctx->compute_pipeline_state.module_hash; 351bf215546Sopenharmony_ci comp->curr = zm; 352bf215546Sopenharmony_ci ctx->compute_pipeline_state.module_hash = zm->hash; 353bf215546Sopenharmony_ci ctx->compute_pipeline_state.final_hash ^= ctx->compute_pipeline_state.module_hash; 354bf215546Sopenharmony_ci ctx->compute_pipeline_state.module_changed = true; 355bf215546Sopenharmony_ci} 356bf215546Sopenharmony_ci 357bf215546Sopenharmony_civoid 358bf215546Sopenharmony_cizink_update_compute_program(struct zink_context *ctx) 359bf215546Sopenharmony_ci{ 360bf215546Sopenharmony_ci update_cs_shader_module(ctx, ctx->curr_compute); 361bf215546Sopenharmony_ci} 362bf215546Sopenharmony_ci 363bf215546Sopenharmony_ciVkPipelineLayout 364bf215546Sopenharmony_cizink_pipeline_layout_create(struct zink_screen *screen, struct zink_program *pg, uint32_t *compat) 365bf215546Sopenharmony_ci{ 366bf215546Sopenharmony_ci VkPipelineLayoutCreateInfo plci = {0}; 367bf215546Sopenharmony_ci plci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; 368bf215546Sopenharmony_ci 369bf215546Sopenharmony_ci plci.pSetLayouts = pg->dsl; 370bf215546Sopenharmony_ci plci.setLayoutCount = pg->num_dsl; 371bf215546Sopenharmony_ci 372bf215546Sopenharmony_ci VkPushConstantRange pcr[2] = {0}; 373bf215546Sopenharmony_ci if (pg->is_compute) { 374bf215546Sopenharmony_ci if (((struct zink_compute_program*)pg)->shader->nir->info.stage == MESA_SHADER_KERNEL) { 375bf215546Sopenharmony_ci pcr[0].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; 376bf215546Sopenharmony_ci pcr[0].offset = 0; 377bf215546Sopenharmony_ci pcr[0].size = sizeof(struct zink_cs_push_constant); 378bf215546Sopenharmony_ci plci.pushConstantRangeCount = 1; 379bf215546Sopenharmony_ci } 380bf215546Sopenharmony_ci } else { 381bf215546Sopenharmony_ci pcr[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; 382bf215546Sopenharmony_ci pcr[0].offset = offsetof(struct zink_gfx_push_constant, draw_mode_is_indexed); 383bf215546Sopenharmony_ci pcr[0].size = 2 * sizeof(unsigned); 384bf215546Sopenharmony_ci pcr[1].stageFlags = VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT; 385bf215546Sopenharmony_ci pcr[1].offset = offsetof(struct zink_gfx_push_constant, default_inner_level); 386bf215546Sopenharmony_ci pcr[1].size = sizeof(float) * 6; 387bf215546Sopenharmony_ci plci.pushConstantRangeCount = 2; 388bf215546Sopenharmony_ci } 389bf215546Sopenharmony_ci plci.pPushConstantRanges = &pcr[0]; 390bf215546Sopenharmony_ci 391bf215546Sopenharmony_ci VkPipelineLayout layout; 392bf215546Sopenharmony_ci VkResult result = VKSCR(CreatePipelineLayout)(screen->dev, &plci, NULL, &layout); 393bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 394bf215546Sopenharmony_ci mesa_loge("vkCreatePipelineLayout failed (%s)", vk_Result_to_str(result)); 395bf215546Sopenharmony_ci return VK_NULL_HANDLE; 396bf215546Sopenharmony_ci } 397bf215546Sopenharmony_ci 398bf215546Sopenharmony_ci *compat = _mesa_hash_data(pg->dsl, pg->num_dsl * sizeof(pg->dsl[0])); 399bf215546Sopenharmony_ci 400bf215546Sopenharmony_ci return layout; 401bf215546Sopenharmony_ci} 402bf215546Sopenharmony_ci 403bf215546Sopenharmony_cistatic void 404bf215546Sopenharmony_ciassign_io(struct zink_gfx_program *prog, struct zink_shader *stages[ZINK_SHADER_COUNT]) 405bf215546Sopenharmony_ci{ 406bf215546Sopenharmony_ci struct zink_shader *shaders[PIPE_SHADER_TYPES]; 407bf215546Sopenharmony_ci 408bf215546Sopenharmony_ci /* build array in pipeline order */ 409bf215546Sopenharmony_ci for (unsigned i = 0; i < ZINK_SHADER_COUNT; i++) 410bf215546Sopenharmony_ci shaders[tgsi_processor_to_shader_stage(i)] = stages[i]; 411bf215546Sopenharmony_ci 412bf215546Sopenharmony_ci for (unsigned i = 0; i < MESA_SHADER_FRAGMENT;) { 413bf215546Sopenharmony_ci nir_shader *producer = shaders[i]->nir; 414bf215546Sopenharmony_ci for (unsigned j = i + 1; j < ZINK_SHADER_COUNT; i++, j++) { 415bf215546Sopenharmony_ci struct zink_shader *consumer = shaders[j]; 416bf215546Sopenharmony_ci if (!consumer) 417bf215546Sopenharmony_ci continue; 418bf215546Sopenharmony_ci if (!prog->nir[producer->info.stage]) 419bf215546Sopenharmony_ci prog->nir[producer->info.stage] = nir_shader_clone(prog, producer); 420bf215546Sopenharmony_ci if (!prog->nir[j]) 421bf215546Sopenharmony_ci prog->nir[j] = nir_shader_clone(prog, consumer->nir); 422bf215546Sopenharmony_ci zink_compiler_assign_io(prog->nir[producer->info.stage], prog->nir[j]); 423bf215546Sopenharmony_ci i = j; 424bf215546Sopenharmony_ci break; 425bf215546Sopenharmony_ci } 426bf215546Sopenharmony_ci } 427bf215546Sopenharmony_ci} 428bf215546Sopenharmony_ci 429bf215546Sopenharmony_cistruct zink_gfx_program * 430bf215546Sopenharmony_cizink_create_gfx_program(struct zink_context *ctx, 431bf215546Sopenharmony_ci struct zink_shader *stages[ZINK_SHADER_COUNT], 432bf215546Sopenharmony_ci unsigned vertices_per_patch) 433bf215546Sopenharmony_ci{ 434bf215546Sopenharmony_ci struct zink_screen *screen = zink_screen(ctx->base.screen); 435bf215546Sopenharmony_ci struct zink_gfx_program *prog = rzalloc(NULL, struct zink_gfx_program); 436bf215546Sopenharmony_ci if (!prog) 437bf215546Sopenharmony_ci goto fail; 438bf215546Sopenharmony_ci 439bf215546Sopenharmony_ci pipe_reference_init(&prog->base.reference, 1); 440bf215546Sopenharmony_ci util_queue_fence_init(&prog->base.cache_fence); 441bf215546Sopenharmony_ci 442bf215546Sopenharmony_ci for (int i = 0; i < ZINK_SHADER_COUNT; ++i) { 443bf215546Sopenharmony_ci list_inithead(&prog->shader_cache[i][0][0]); 444bf215546Sopenharmony_ci list_inithead(&prog->shader_cache[i][0][1]); 445bf215546Sopenharmony_ci list_inithead(&prog->shader_cache[i][1][0]); 446bf215546Sopenharmony_ci list_inithead(&prog->shader_cache[i][1][1]); 447bf215546Sopenharmony_ci if (stages[i]) { 448bf215546Sopenharmony_ci prog->shaders[i] = stages[i]; 449bf215546Sopenharmony_ci prog->stages_present |= BITFIELD_BIT(i); 450bf215546Sopenharmony_ci } 451bf215546Sopenharmony_ci } 452bf215546Sopenharmony_ci if (stages[PIPE_SHADER_TESS_EVAL] && !stages[PIPE_SHADER_TESS_CTRL]) { 453bf215546Sopenharmony_ci prog->shaders[PIPE_SHADER_TESS_EVAL]->generated = 454bf215546Sopenharmony_ci prog->shaders[PIPE_SHADER_TESS_CTRL] = 455bf215546Sopenharmony_ci zink_shader_tcs_create(screen, stages[PIPE_SHADER_VERTEX], vertices_per_patch); 456bf215546Sopenharmony_ci prog->stages_present |= BITFIELD_BIT(PIPE_SHADER_TESS_CTRL); 457bf215546Sopenharmony_ci } 458bf215546Sopenharmony_ci 459bf215546Sopenharmony_ci assign_io(prog, prog->shaders); 460bf215546Sopenharmony_ci 461bf215546Sopenharmony_ci if (stages[PIPE_SHADER_GEOMETRY]) 462bf215546Sopenharmony_ci prog->last_vertex_stage = stages[PIPE_SHADER_GEOMETRY]; 463bf215546Sopenharmony_ci else if (stages[PIPE_SHADER_TESS_EVAL]) 464bf215546Sopenharmony_ci prog->last_vertex_stage = stages[PIPE_SHADER_TESS_EVAL]; 465bf215546Sopenharmony_ci else 466bf215546Sopenharmony_ci prog->last_vertex_stage = stages[PIPE_SHADER_VERTEX]; 467bf215546Sopenharmony_ci 468bf215546Sopenharmony_ci for (int i = 0; i < ARRAY_SIZE(prog->pipelines); ++i) { 469bf215546Sopenharmony_ci _mesa_hash_table_init(&prog->pipelines[i], prog, NULL, equals_gfx_pipeline_state); 470bf215546Sopenharmony_ci /* only need first 3/4 for point/line/tri/patch */ 471bf215546Sopenharmony_ci if (screen->info.have_EXT_extended_dynamic_state && 472bf215546Sopenharmony_ci i == (prog->last_vertex_stage->nir->info.stage == MESA_SHADER_TESS_EVAL ? 4 : 3)) 473bf215546Sopenharmony_ci break; 474bf215546Sopenharmony_ci } 475bf215546Sopenharmony_ci 476bf215546Sopenharmony_ci struct mesa_sha1 sctx; 477bf215546Sopenharmony_ci _mesa_sha1_init(&sctx); 478bf215546Sopenharmony_ci for (int i = 0; i < ZINK_SHADER_COUNT; ++i) { 479bf215546Sopenharmony_ci if (prog->shaders[i]) { 480bf215546Sopenharmony_ci simple_mtx_lock(&prog->shaders[i]->lock); 481bf215546Sopenharmony_ci _mesa_set_add(prog->shaders[i]->programs, prog); 482bf215546Sopenharmony_ci simple_mtx_unlock(&prog->shaders[i]->lock); 483bf215546Sopenharmony_ci zink_gfx_program_reference(ctx, NULL, prog); 484bf215546Sopenharmony_ci _mesa_sha1_update(&sctx, prog->shaders[i]->base.sha1, sizeof(prog->shaders[i]->base.sha1)); 485bf215546Sopenharmony_ci } 486bf215546Sopenharmony_ci } 487bf215546Sopenharmony_ci _mesa_sha1_final(&sctx, prog->base.sha1); 488bf215546Sopenharmony_ci 489bf215546Sopenharmony_ci if (!screen->descriptor_program_init(ctx, &prog->base)) 490bf215546Sopenharmony_ci goto fail; 491bf215546Sopenharmony_ci 492bf215546Sopenharmony_ci zink_screen_get_pipeline_cache(screen, &prog->base); 493bf215546Sopenharmony_ci return prog; 494bf215546Sopenharmony_ci 495bf215546Sopenharmony_cifail: 496bf215546Sopenharmony_ci if (prog) 497bf215546Sopenharmony_ci zink_destroy_gfx_program(ctx, prog); 498bf215546Sopenharmony_ci return NULL; 499bf215546Sopenharmony_ci} 500bf215546Sopenharmony_ci 501bf215546Sopenharmony_cistatic uint32_t 502bf215546Sopenharmony_cihash_compute_pipeline_state(const void *key) 503bf215546Sopenharmony_ci{ 504bf215546Sopenharmony_ci const struct zink_compute_pipeline_state *state = key; 505bf215546Sopenharmony_ci uint32_t hash = _mesa_hash_data(state, offsetof(struct zink_compute_pipeline_state, hash)); 506bf215546Sopenharmony_ci if (state->use_local_size) 507bf215546Sopenharmony_ci hash = XXH32(&state->local_size[0], sizeof(state->local_size), hash); 508bf215546Sopenharmony_ci return hash; 509bf215546Sopenharmony_ci} 510bf215546Sopenharmony_ci 511bf215546Sopenharmony_civoid 512bf215546Sopenharmony_cizink_program_update_compute_pipeline_state(struct zink_context *ctx, struct zink_compute_program *comp, const uint block[3]) 513bf215546Sopenharmony_ci{ 514bf215546Sopenharmony_ci struct zink_shader *zs = comp->shader; 515bf215546Sopenharmony_ci bool use_local_size = !(zs->nir->info.workgroup_size[0] || 516bf215546Sopenharmony_ci zs->nir->info.workgroup_size[1] || 517bf215546Sopenharmony_ci zs->nir->info.workgroup_size[2]); 518bf215546Sopenharmony_ci if (ctx->compute_pipeline_state.use_local_size != use_local_size) 519bf215546Sopenharmony_ci ctx->compute_pipeline_state.dirty = true; 520bf215546Sopenharmony_ci ctx->compute_pipeline_state.use_local_size = use_local_size; 521bf215546Sopenharmony_ci 522bf215546Sopenharmony_ci if (ctx->compute_pipeline_state.use_local_size) { 523bf215546Sopenharmony_ci for (int i = 0; i < ARRAY_SIZE(ctx->compute_pipeline_state.local_size); i++) { 524bf215546Sopenharmony_ci if (ctx->compute_pipeline_state.local_size[i] != block[i]) 525bf215546Sopenharmony_ci ctx->compute_pipeline_state.dirty = true; 526bf215546Sopenharmony_ci ctx->compute_pipeline_state.local_size[i] = block[i]; 527bf215546Sopenharmony_ci } 528bf215546Sopenharmony_ci } else 529bf215546Sopenharmony_ci ctx->compute_pipeline_state.local_size[0] = 530bf215546Sopenharmony_ci ctx->compute_pipeline_state.local_size[1] = 531bf215546Sopenharmony_ci ctx->compute_pipeline_state.local_size[2] = 0; 532bf215546Sopenharmony_ci} 533bf215546Sopenharmony_ci 534bf215546Sopenharmony_cistatic bool 535bf215546Sopenharmony_ciequals_compute_pipeline_state(const void *a, const void *b) 536bf215546Sopenharmony_ci{ 537bf215546Sopenharmony_ci const struct zink_compute_pipeline_state *sa = a; 538bf215546Sopenharmony_ci const struct zink_compute_pipeline_state *sb = b; 539bf215546Sopenharmony_ci return !memcmp(a, b, offsetof(struct zink_compute_pipeline_state, hash)) && 540bf215546Sopenharmony_ci sa->module == sb->module; 541bf215546Sopenharmony_ci} 542bf215546Sopenharmony_ci 543bf215546Sopenharmony_cistruct zink_compute_program * 544bf215546Sopenharmony_cizink_create_compute_program(struct zink_context *ctx, struct zink_shader *shader) 545bf215546Sopenharmony_ci{ 546bf215546Sopenharmony_ci struct zink_screen *screen = zink_screen(ctx->base.screen); 547bf215546Sopenharmony_ci struct zink_compute_program *comp = rzalloc(NULL, struct zink_compute_program); 548bf215546Sopenharmony_ci if (!comp) 549bf215546Sopenharmony_ci goto fail; 550bf215546Sopenharmony_ci 551bf215546Sopenharmony_ci pipe_reference_init(&comp->base.reference, 1); 552bf215546Sopenharmony_ci util_queue_fence_init(&comp->base.cache_fence); 553bf215546Sopenharmony_ci comp->base.is_compute = true; 554bf215546Sopenharmony_ci 555bf215546Sopenharmony_ci comp->curr = comp->module = CALLOC_STRUCT(zink_shader_module); 556bf215546Sopenharmony_ci assert(comp->module); 557bf215546Sopenharmony_ci comp->module->shader = zink_shader_compile(screen, shader, shader->nir, NULL); 558bf215546Sopenharmony_ci assert(comp->module->shader); 559bf215546Sopenharmony_ci list_inithead(&comp->shader_cache[0]); 560bf215546Sopenharmony_ci list_inithead(&comp->shader_cache[1]); 561bf215546Sopenharmony_ci 562bf215546Sopenharmony_ci comp->pipelines = _mesa_hash_table_create(NULL, NULL, 563bf215546Sopenharmony_ci equals_compute_pipeline_state); 564bf215546Sopenharmony_ci 565bf215546Sopenharmony_ci _mesa_set_add(shader->programs, comp); 566bf215546Sopenharmony_ci comp->shader = shader; 567bf215546Sopenharmony_ci memcpy(comp->base.sha1, shader->base.sha1, sizeof(shader->base.sha1)); 568bf215546Sopenharmony_ci 569bf215546Sopenharmony_ci if (!screen->descriptor_program_init(ctx, &comp->base)) 570bf215546Sopenharmony_ci goto fail; 571bf215546Sopenharmony_ci 572bf215546Sopenharmony_ci zink_screen_get_pipeline_cache(screen, &comp->base); 573bf215546Sopenharmony_ci return comp; 574bf215546Sopenharmony_ci 575bf215546Sopenharmony_cifail: 576bf215546Sopenharmony_ci if (comp) 577bf215546Sopenharmony_ci zink_destroy_compute_program(ctx, comp); 578bf215546Sopenharmony_ci return NULL; 579bf215546Sopenharmony_ci} 580bf215546Sopenharmony_ci 581bf215546Sopenharmony_ciuint32_t 582bf215546Sopenharmony_cizink_program_get_descriptor_usage(struct zink_context *ctx, enum pipe_shader_type stage, enum zink_descriptor_type type) 583bf215546Sopenharmony_ci{ 584bf215546Sopenharmony_ci struct zink_shader *zs = NULL; 585bf215546Sopenharmony_ci switch (stage) { 586bf215546Sopenharmony_ci case PIPE_SHADER_VERTEX: 587bf215546Sopenharmony_ci case PIPE_SHADER_TESS_CTRL: 588bf215546Sopenharmony_ci case PIPE_SHADER_TESS_EVAL: 589bf215546Sopenharmony_ci case PIPE_SHADER_GEOMETRY: 590bf215546Sopenharmony_ci case PIPE_SHADER_FRAGMENT: 591bf215546Sopenharmony_ci zs = ctx->gfx_stages[stage]; 592bf215546Sopenharmony_ci break; 593bf215546Sopenharmony_ci case PIPE_SHADER_COMPUTE: { 594bf215546Sopenharmony_ci zs = ctx->compute_stage; 595bf215546Sopenharmony_ci break; 596bf215546Sopenharmony_ci } 597bf215546Sopenharmony_ci default: 598bf215546Sopenharmony_ci unreachable("unknown shader type"); 599bf215546Sopenharmony_ci } 600bf215546Sopenharmony_ci if (!zs) 601bf215546Sopenharmony_ci return 0; 602bf215546Sopenharmony_ci switch (type) { 603bf215546Sopenharmony_ci case ZINK_DESCRIPTOR_TYPE_UBO: 604bf215546Sopenharmony_ci return zs->ubos_used; 605bf215546Sopenharmony_ci case ZINK_DESCRIPTOR_TYPE_SSBO: 606bf215546Sopenharmony_ci return zs->ssbos_used; 607bf215546Sopenharmony_ci case ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW: 608bf215546Sopenharmony_ci return BITSET_TEST_RANGE(zs->nir->info.textures_used, 0, PIPE_MAX_SAMPLERS - 1); 609bf215546Sopenharmony_ci case ZINK_DESCRIPTOR_TYPE_IMAGE: 610bf215546Sopenharmony_ci return BITSET_TEST_RANGE(zs->nir->info.images_used, 0, PIPE_MAX_SAMPLERS - 1); 611bf215546Sopenharmony_ci default: 612bf215546Sopenharmony_ci unreachable("unknown descriptor type!"); 613bf215546Sopenharmony_ci } 614bf215546Sopenharmony_ci return 0; 615bf215546Sopenharmony_ci} 616bf215546Sopenharmony_ci 617bf215546Sopenharmony_cibool 618bf215546Sopenharmony_cizink_program_descriptor_is_buffer(struct zink_context *ctx, enum pipe_shader_type stage, enum zink_descriptor_type type, unsigned i) 619bf215546Sopenharmony_ci{ 620bf215546Sopenharmony_ci struct zink_shader *zs = NULL; 621bf215546Sopenharmony_ci switch (stage) { 622bf215546Sopenharmony_ci case PIPE_SHADER_VERTEX: 623bf215546Sopenharmony_ci case PIPE_SHADER_TESS_CTRL: 624bf215546Sopenharmony_ci case PIPE_SHADER_TESS_EVAL: 625bf215546Sopenharmony_ci case PIPE_SHADER_GEOMETRY: 626bf215546Sopenharmony_ci case PIPE_SHADER_FRAGMENT: 627bf215546Sopenharmony_ci zs = ctx->gfx_stages[stage]; 628bf215546Sopenharmony_ci break; 629bf215546Sopenharmony_ci case PIPE_SHADER_COMPUTE: { 630bf215546Sopenharmony_ci zs = ctx->compute_stage; 631bf215546Sopenharmony_ci break; 632bf215546Sopenharmony_ci } 633bf215546Sopenharmony_ci default: 634bf215546Sopenharmony_ci unreachable("unknown shader type"); 635bf215546Sopenharmony_ci } 636bf215546Sopenharmony_ci if (!zs) 637bf215546Sopenharmony_ci return false; 638bf215546Sopenharmony_ci return zink_shader_descriptor_is_buffer(zs, type, i); 639bf215546Sopenharmony_ci} 640bf215546Sopenharmony_ci 641bf215546Sopenharmony_cistatic unsigned 642bf215546Sopenharmony_ciget_num_bindings(struct zink_shader *zs, enum zink_descriptor_type type) 643bf215546Sopenharmony_ci{ 644bf215546Sopenharmony_ci switch (type) { 645bf215546Sopenharmony_ci case ZINK_DESCRIPTOR_TYPE_UBO: 646bf215546Sopenharmony_ci case ZINK_DESCRIPTOR_TYPE_SSBO: 647bf215546Sopenharmony_ci return zs->num_bindings[type]; 648bf215546Sopenharmony_ci default: 649bf215546Sopenharmony_ci break; 650bf215546Sopenharmony_ci } 651bf215546Sopenharmony_ci unsigned num_bindings = 0; 652bf215546Sopenharmony_ci for (int i = 0; i < zs->num_bindings[type]; i++) 653bf215546Sopenharmony_ci num_bindings += zs->bindings[type][i].size; 654bf215546Sopenharmony_ci return num_bindings; 655bf215546Sopenharmony_ci} 656bf215546Sopenharmony_ci 657bf215546Sopenharmony_ciunsigned 658bf215546Sopenharmony_cizink_program_num_bindings_typed(const struct zink_program *pg, enum zink_descriptor_type type, bool is_compute) 659bf215546Sopenharmony_ci{ 660bf215546Sopenharmony_ci unsigned num_bindings = 0; 661bf215546Sopenharmony_ci if (is_compute) { 662bf215546Sopenharmony_ci struct zink_compute_program *comp = (void*)pg; 663bf215546Sopenharmony_ci return get_num_bindings(comp->shader, type); 664bf215546Sopenharmony_ci } 665bf215546Sopenharmony_ci struct zink_gfx_program *prog = (void*)pg; 666bf215546Sopenharmony_ci for (unsigned i = 0; i < ZINK_SHADER_COUNT; i++) { 667bf215546Sopenharmony_ci if (prog->shaders[i]) 668bf215546Sopenharmony_ci num_bindings += get_num_bindings(prog->shaders[i], type); 669bf215546Sopenharmony_ci } 670bf215546Sopenharmony_ci return num_bindings; 671bf215546Sopenharmony_ci} 672bf215546Sopenharmony_ci 673bf215546Sopenharmony_ciunsigned 674bf215546Sopenharmony_cizink_program_num_bindings(const struct zink_program *pg, bool is_compute) 675bf215546Sopenharmony_ci{ 676bf215546Sopenharmony_ci unsigned num_bindings = 0; 677bf215546Sopenharmony_ci for (unsigned i = 0; i < ZINK_DESCRIPTOR_TYPES; i++) 678bf215546Sopenharmony_ci num_bindings += zink_program_num_bindings_typed(pg, i, is_compute); 679bf215546Sopenharmony_ci return num_bindings; 680bf215546Sopenharmony_ci} 681bf215546Sopenharmony_ci 682bf215546Sopenharmony_civoid 683bf215546Sopenharmony_cizink_destroy_gfx_program(struct zink_context *ctx, 684bf215546Sopenharmony_ci struct zink_gfx_program *prog) 685bf215546Sopenharmony_ci{ 686bf215546Sopenharmony_ci struct zink_screen *screen = zink_screen(ctx->base.screen); 687bf215546Sopenharmony_ci util_queue_fence_wait(&prog->base.cache_fence); 688bf215546Sopenharmony_ci if (prog->base.layout) 689bf215546Sopenharmony_ci VKSCR(DestroyPipelineLayout)(screen->dev, prog->base.layout, NULL); 690bf215546Sopenharmony_ci 691bf215546Sopenharmony_ci for (int i = 0; i < ZINK_SHADER_COUNT; ++i) { 692bf215546Sopenharmony_ci if (prog->shaders[i]) { 693bf215546Sopenharmony_ci _mesa_set_remove_key(prog->shaders[i]->programs, prog); 694bf215546Sopenharmony_ci prog->shaders[i] = NULL; 695bf215546Sopenharmony_ci } 696bf215546Sopenharmony_ci destroy_shader_cache(screen, &prog->shader_cache[i][0][0]); 697bf215546Sopenharmony_ci destroy_shader_cache(screen, &prog->shader_cache[i][0][1]); 698bf215546Sopenharmony_ci destroy_shader_cache(screen, &prog->shader_cache[i][1][0]); 699bf215546Sopenharmony_ci destroy_shader_cache(screen, &prog->shader_cache[i][1][1]); 700bf215546Sopenharmony_ci ralloc_free(prog->nir[i]); 701bf215546Sopenharmony_ci } 702bf215546Sopenharmony_ci 703bf215546Sopenharmony_ci unsigned max_idx = ARRAY_SIZE(prog->pipelines); 704bf215546Sopenharmony_ci if (screen->info.have_EXT_extended_dynamic_state) { 705bf215546Sopenharmony_ci /* only need first 3/4 for point/line/tri/patch */ 706bf215546Sopenharmony_ci if ((prog->stages_present & 707bf215546Sopenharmony_ci (BITFIELD_BIT(PIPE_SHADER_TESS_EVAL) | BITFIELD_BIT(PIPE_SHADER_GEOMETRY))) == 708bf215546Sopenharmony_ci BITFIELD_BIT(PIPE_SHADER_TESS_EVAL)) 709bf215546Sopenharmony_ci max_idx = 4; 710bf215546Sopenharmony_ci else 711bf215546Sopenharmony_ci max_idx = 3; 712bf215546Sopenharmony_ci max_idx++; 713bf215546Sopenharmony_ci } 714bf215546Sopenharmony_ci 715bf215546Sopenharmony_ci for (int i = 0; i < max_idx; ++i) { 716bf215546Sopenharmony_ci hash_table_foreach(&prog->pipelines[i], entry) { 717bf215546Sopenharmony_ci struct gfx_pipeline_cache_entry *pc_entry = entry->data; 718bf215546Sopenharmony_ci 719bf215546Sopenharmony_ci VKSCR(DestroyPipeline)(screen->dev, pc_entry->pipeline, NULL); 720bf215546Sopenharmony_ci free(pc_entry); 721bf215546Sopenharmony_ci } 722bf215546Sopenharmony_ci } 723bf215546Sopenharmony_ci if (prog->base.pipeline_cache) 724bf215546Sopenharmony_ci VKSCR(DestroyPipelineCache)(screen->dev, prog->base.pipeline_cache, NULL); 725bf215546Sopenharmony_ci screen->descriptor_program_deinit(ctx, &prog->base); 726bf215546Sopenharmony_ci 727bf215546Sopenharmony_ci ralloc_free(prog); 728bf215546Sopenharmony_ci} 729bf215546Sopenharmony_ci 730bf215546Sopenharmony_civoid 731bf215546Sopenharmony_cizink_destroy_compute_program(struct zink_context *ctx, 732bf215546Sopenharmony_ci struct zink_compute_program *comp) 733bf215546Sopenharmony_ci{ 734bf215546Sopenharmony_ci struct zink_screen *screen = zink_screen(ctx->base.screen); 735bf215546Sopenharmony_ci util_queue_fence_wait(&comp->base.cache_fence); 736bf215546Sopenharmony_ci if (comp->base.layout) 737bf215546Sopenharmony_ci VKSCR(DestroyPipelineLayout)(screen->dev, comp->base.layout, NULL); 738bf215546Sopenharmony_ci 739bf215546Sopenharmony_ci if (comp->shader) 740bf215546Sopenharmony_ci _mesa_set_remove_key(comp->shader->programs, comp); 741bf215546Sopenharmony_ci destroy_shader_cache(screen, &comp->shader_cache[0]); 742bf215546Sopenharmony_ci destroy_shader_cache(screen, &comp->shader_cache[1]); 743bf215546Sopenharmony_ci 744bf215546Sopenharmony_ci hash_table_foreach(comp->pipelines, entry) { 745bf215546Sopenharmony_ci struct compute_pipeline_cache_entry *pc_entry = entry->data; 746bf215546Sopenharmony_ci 747bf215546Sopenharmony_ci VKSCR(DestroyPipeline)(screen->dev, pc_entry->pipeline, NULL); 748bf215546Sopenharmony_ci free(pc_entry); 749bf215546Sopenharmony_ci } 750bf215546Sopenharmony_ci _mesa_hash_table_destroy(comp->pipelines, NULL); 751bf215546Sopenharmony_ci VKSCR(DestroyShaderModule)(screen->dev, comp->module->shader, NULL); 752bf215546Sopenharmony_ci free(comp->module); 753bf215546Sopenharmony_ci if (comp->base.pipeline_cache) 754bf215546Sopenharmony_ci VKSCR(DestroyPipelineCache)(screen->dev, comp->base.pipeline_cache, NULL); 755bf215546Sopenharmony_ci screen->descriptor_program_deinit(ctx, &comp->base); 756bf215546Sopenharmony_ci 757bf215546Sopenharmony_ci ralloc_free(comp); 758bf215546Sopenharmony_ci} 759bf215546Sopenharmony_ci 760bf215546Sopenharmony_cistatic unsigned 761bf215546Sopenharmony_ciget_pipeline_idx(bool have_EXT_extended_dynamic_state, enum pipe_prim_type mode, VkPrimitiveTopology vkmode) 762bf215546Sopenharmony_ci{ 763bf215546Sopenharmony_ci /* VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY specifies that the topology state in 764bf215546Sopenharmony_ci * VkPipelineInputAssemblyStateCreateInfo only specifies the topology class, 765bf215546Sopenharmony_ci * and the specific topology order and adjacency must be set dynamically 766bf215546Sopenharmony_ci * with vkCmdSetPrimitiveTopology before any drawing commands. 767bf215546Sopenharmony_ci */ 768bf215546Sopenharmony_ci if (have_EXT_extended_dynamic_state) { 769bf215546Sopenharmony_ci if (mode == PIPE_PRIM_PATCHES) 770bf215546Sopenharmony_ci return 3; 771bf215546Sopenharmony_ci switch (u_reduced_prim(mode)) { 772bf215546Sopenharmony_ci case PIPE_PRIM_POINTS: 773bf215546Sopenharmony_ci return 0; 774bf215546Sopenharmony_ci case PIPE_PRIM_LINES: 775bf215546Sopenharmony_ci return 1; 776bf215546Sopenharmony_ci default: 777bf215546Sopenharmony_ci return 2; 778bf215546Sopenharmony_ci } 779bf215546Sopenharmony_ci } 780bf215546Sopenharmony_ci return vkmode; 781bf215546Sopenharmony_ci} 782bf215546Sopenharmony_ci 783bf215546Sopenharmony_ci/* 784bf215546Sopenharmony_ci VUID-vkCmdBindVertexBuffers2-pStrides-06209 785bf215546Sopenharmony_ci If pStrides is not NULL each element of pStrides must be either 0 or greater than or equal 786bf215546Sopenharmony_ci to the maximum extent of all vertex input attributes fetched from the corresponding 787bf215546Sopenharmony_ci binding, where the extent is calculated as the VkVertexInputAttributeDescription::offset 788bf215546Sopenharmony_ci plus VkVertexInputAttributeDescription::format size 789bf215546Sopenharmony_ci 790bf215546Sopenharmony_ci * thus, if the stride doesn't meet the minimum requirement for a binding, 791bf215546Sopenharmony_ci * disable the dynamic state here and use a fully-baked pipeline 792bf215546Sopenharmony_ci */ 793bf215546Sopenharmony_cistatic bool 794bf215546Sopenharmony_cicheck_vertex_strides(struct zink_context *ctx) 795bf215546Sopenharmony_ci{ 796bf215546Sopenharmony_ci const struct zink_vertex_elements_state *ves = ctx->element_state; 797bf215546Sopenharmony_ci for (unsigned i = 0; i < ves->hw_state.num_bindings; i++) { 798bf215546Sopenharmony_ci const struct pipe_vertex_buffer *vb = ctx->vertex_buffers + ves->binding_map[i]; 799bf215546Sopenharmony_ci unsigned stride = vb->buffer.resource ? vb->stride : 0; 800bf215546Sopenharmony_ci if (stride && stride < ves->min_stride[i]) 801bf215546Sopenharmony_ci return false; 802bf215546Sopenharmony_ci } 803bf215546Sopenharmony_ci return true; 804bf215546Sopenharmony_ci} 805bf215546Sopenharmony_ci 806bf215546Sopenharmony_ciVkPipeline 807bf215546Sopenharmony_cizink_get_gfx_pipeline(struct zink_context *ctx, 808bf215546Sopenharmony_ci struct zink_gfx_program *prog, 809bf215546Sopenharmony_ci struct zink_gfx_pipeline_state *state, 810bf215546Sopenharmony_ci enum pipe_prim_type mode) 811bf215546Sopenharmony_ci{ 812bf215546Sopenharmony_ci struct zink_screen *screen = zink_screen(ctx->base.screen); 813bf215546Sopenharmony_ci const bool have_EXT_vertex_input_dynamic_state = screen->info.have_EXT_vertex_input_dynamic_state; 814bf215546Sopenharmony_ci const bool have_EXT_extended_dynamic_state = screen->info.have_EXT_extended_dynamic_state; 815bf215546Sopenharmony_ci bool uses_dynamic_stride = state->uses_dynamic_stride; 816bf215546Sopenharmony_ci 817bf215546Sopenharmony_ci VkPrimitiveTopology vkmode = zink_primitive_topology(mode); 818bf215546Sopenharmony_ci const unsigned idx = get_pipeline_idx(screen->info.have_EXT_extended_dynamic_state, mode, vkmode); 819bf215546Sopenharmony_ci assert(idx <= ARRAY_SIZE(prog->pipelines)); 820bf215546Sopenharmony_ci if (!state->dirty && !state->modules_changed && 821bf215546Sopenharmony_ci (have_EXT_vertex_input_dynamic_state || !ctx->vertex_state_changed) && 822bf215546Sopenharmony_ci idx == state->idx) 823bf215546Sopenharmony_ci return state->pipeline; 824bf215546Sopenharmony_ci 825bf215546Sopenharmony_ci struct hash_entry *entry = NULL; 826bf215546Sopenharmony_ci 827bf215546Sopenharmony_ci if (state->dirty) { 828bf215546Sopenharmony_ci if (state->pipeline) //avoid on first hash 829bf215546Sopenharmony_ci state->final_hash ^= state->hash; 830bf215546Sopenharmony_ci state->hash = hash_gfx_pipeline_state(state); 831bf215546Sopenharmony_ci state->final_hash ^= state->hash; 832bf215546Sopenharmony_ci state->dirty = false; 833bf215546Sopenharmony_ci } 834bf215546Sopenharmony_ci if (!have_EXT_vertex_input_dynamic_state && ctx->vertex_state_changed) { 835bf215546Sopenharmony_ci if (state->pipeline) 836bf215546Sopenharmony_ci state->final_hash ^= state->vertex_hash; 837bf215546Sopenharmony_ci if (have_EXT_extended_dynamic_state) 838bf215546Sopenharmony_ci uses_dynamic_stride = check_vertex_strides(ctx); 839bf215546Sopenharmony_ci if (!uses_dynamic_stride) { 840bf215546Sopenharmony_ci uint32_t hash = 0; 841bf215546Sopenharmony_ci /* if we don't have dynamic states, we have to hash the enabled vertex buffer bindings */ 842bf215546Sopenharmony_ci uint32_t vertex_buffers_enabled_mask = state->vertex_buffers_enabled_mask; 843bf215546Sopenharmony_ci hash = XXH32(&vertex_buffers_enabled_mask, sizeof(uint32_t), hash); 844bf215546Sopenharmony_ci 845bf215546Sopenharmony_ci for (unsigned i = 0; i < state->element_state->num_bindings; i++) { 846bf215546Sopenharmony_ci const unsigned buffer_id = ctx->element_state->binding_map[i]; 847bf215546Sopenharmony_ci struct pipe_vertex_buffer *vb = ctx->vertex_buffers + buffer_id; 848bf215546Sopenharmony_ci state->vertex_strides[buffer_id] = vb->buffer.resource ? vb->stride : 0; 849bf215546Sopenharmony_ci hash = XXH32(&state->vertex_strides[buffer_id], sizeof(uint32_t), hash); 850bf215546Sopenharmony_ci } 851bf215546Sopenharmony_ci state->vertex_hash = hash ^ state->element_state->hash; 852bf215546Sopenharmony_ci } else 853bf215546Sopenharmony_ci state->vertex_hash = state->element_state->hash; 854bf215546Sopenharmony_ci state->final_hash ^= state->vertex_hash; 855bf215546Sopenharmony_ci } 856bf215546Sopenharmony_ci state->modules_changed = false; 857bf215546Sopenharmony_ci state->uses_dynamic_stride = uses_dynamic_stride; 858bf215546Sopenharmony_ci ctx->vertex_state_changed = false; 859bf215546Sopenharmony_ci 860bf215546Sopenharmony_ci entry = _mesa_hash_table_search_pre_hashed(&prog->pipelines[idx], state->final_hash, state); 861bf215546Sopenharmony_ci 862bf215546Sopenharmony_ci if (!entry) { 863bf215546Sopenharmony_ci util_queue_fence_wait(&prog->base.cache_fence); 864bf215546Sopenharmony_ci VkPipeline pipeline = zink_create_gfx_pipeline(screen, prog, state, 865bf215546Sopenharmony_ci ctx->element_state->binding_map, 866bf215546Sopenharmony_ci vkmode); 867bf215546Sopenharmony_ci if (pipeline == VK_NULL_HANDLE) 868bf215546Sopenharmony_ci return VK_NULL_HANDLE; 869bf215546Sopenharmony_ci 870bf215546Sopenharmony_ci zink_screen_update_pipeline_cache(screen, &prog->base); 871bf215546Sopenharmony_ci struct gfx_pipeline_cache_entry *pc_entry = CALLOC_STRUCT(gfx_pipeline_cache_entry); 872bf215546Sopenharmony_ci if (!pc_entry) 873bf215546Sopenharmony_ci return VK_NULL_HANDLE; 874bf215546Sopenharmony_ci 875bf215546Sopenharmony_ci memcpy(&pc_entry->state, state, sizeof(*state)); 876bf215546Sopenharmony_ci pc_entry->pipeline = pipeline; 877bf215546Sopenharmony_ci 878bf215546Sopenharmony_ci entry = _mesa_hash_table_insert_pre_hashed(&prog->pipelines[idx], state->final_hash, pc_entry, pc_entry); 879bf215546Sopenharmony_ci assert(entry); 880bf215546Sopenharmony_ci } 881bf215546Sopenharmony_ci 882bf215546Sopenharmony_ci struct gfx_pipeline_cache_entry *cache_entry = entry->data; 883bf215546Sopenharmony_ci state->pipeline = cache_entry->pipeline; 884bf215546Sopenharmony_ci state->idx = idx; 885bf215546Sopenharmony_ci return state->pipeline; 886bf215546Sopenharmony_ci} 887bf215546Sopenharmony_ci 888bf215546Sopenharmony_ciVkPipeline 889bf215546Sopenharmony_cizink_get_compute_pipeline(struct zink_screen *screen, 890bf215546Sopenharmony_ci struct zink_compute_program *comp, 891bf215546Sopenharmony_ci struct zink_compute_pipeline_state *state) 892bf215546Sopenharmony_ci{ 893bf215546Sopenharmony_ci struct hash_entry *entry = NULL; 894bf215546Sopenharmony_ci 895bf215546Sopenharmony_ci if (!state->dirty && !state->module_changed) 896bf215546Sopenharmony_ci return state->pipeline; 897bf215546Sopenharmony_ci if (state->dirty) { 898bf215546Sopenharmony_ci if (state->pipeline) //avoid on first hash 899bf215546Sopenharmony_ci state->final_hash ^= state->hash; 900bf215546Sopenharmony_ci state->hash = hash_compute_pipeline_state(state); 901bf215546Sopenharmony_ci state->dirty = false; 902bf215546Sopenharmony_ci state->final_hash ^= state->hash; 903bf215546Sopenharmony_ci } 904bf215546Sopenharmony_ci entry = _mesa_hash_table_search_pre_hashed(comp->pipelines, state->final_hash, state); 905bf215546Sopenharmony_ci 906bf215546Sopenharmony_ci if (!entry) { 907bf215546Sopenharmony_ci util_queue_fence_wait(&comp->base.cache_fence); 908bf215546Sopenharmony_ci VkPipeline pipeline = zink_create_compute_pipeline(screen, comp, state); 909bf215546Sopenharmony_ci 910bf215546Sopenharmony_ci if (pipeline == VK_NULL_HANDLE) 911bf215546Sopenharmony_ci return VK_NULL_HANDLE; 912bf215546Sopenharmony_ci 913bf215546Sopenharmony_ci struct compute_pipeline_cache_entry *pc_entry = CALLOC_STRUCT(compute_pipeline_cache_entry); 914bf215546Sopenharmony_ci if (!pc_entry) 915bf215546Sopenharmony_ci return VK_NULL_HANDLE; 916bf215546Sopenharmony_ci 917bf215546Sopenharmony_ci memcpy(&pc_entry->state, state, sizeof(*state)); 918bf215546Sopenharmony_ci pc_entry->pipeline = pipeline; 919bf215546Sopenharmony_ci 920bf215546Sopenharmony_ci entry = _mesa_hash_table_insert_pre_hashed(comp->pipelines, state->final_hash, pc_entry, pc_entry); 921bf215546Sopenharmony_ci assert(entry); 922bf215546Sopenharmony_ci } 923bf215546Sopenharmony_ci 924bf215546Sopenharmony_ci struct compute_pipeline_cache_entry *cache_entry = entry->data; 925bf215546Sopenharmony_ci state->pipeline = cache_entry->pipeline; 926bf215546Sopenharmony_ci return state->pipeline; 927bf215546Sopenharmony_ci} 928bf215546Sopenharmony_ci 929bf215546Sopenharmony_cistatic inline void 930bf215546Sopenharmony_cibind_stage(struct zink_context *ctx, enum pipe_shader_type stage, 931bf215546Sopenharmony_ci struct zink_shader *shader) 932bf215546Sopenharmony_ci{ 933bf215546Sopenharmony_ci if (shader && shader->nir->info.num_inlinable_uniforms) 934bf215546Sopenharmony_ci ctx->shader_has_inlinable_uniforms_mask |= 1 << stage; 935bf215546Sopenharmony_ci else 936bf215546Sopenharmony_ci ctx->shader_has_inlinable_uniforms_mask &= ~(1 << stage); 937bf215546Sopenharmony_ci 938bf215546Sopenharmony_ci if (stage == PIPE_SHADER_COMPUTE) { 939bf215546Sopenharmony_ci if (ctx->compute_stage) { 940bf215546Sopenharmony_ci ctx->compute_pipeline_state.final_hash ^= ctx->compute_pipeline_state.module_hash; 941bf215546Sopenharmony_ci ctx->compute_pipeline_state.module = VK_NULL_HANDLE; 942bf215546Sopenharmony_ci ctx->compute_pipeline_state.module_hash = 0; 943bf215546Sopenharmony_ci } 944bf215546Sopenharmony_ci if (shader && shader != ctx->compute_stage) { 945bf215546Sopenharmony_ci struct hash_entry *entry = _mesa_hash_table_search(&ctx->compute_program_cache, shader); 946bf215546Sopenharmony_ci if (entry) { 947bf215546Sopenharmony_ci ctx->compute_pipeline_state.dirty = true; 948bf215546Sopenharmony_ci ctx->curr_compute = entry->data; 949bf215546Sopenharmony_ci } else { 950bf215546Sopenharmony_ci struct zink_compute_program *comp = zink_create_compute_program(ctx, shader); 951bf215546Sopenharmony_ci _mesa_hash_table_insert(&ctx->compute_program_cache, comp->shader, comp); 952bf215546Sopenharmony_ci ctx->compute_pipeline_state.dirty = true; 953bf215546Sopenharmony_ci ctx->curr_compute = comp; 954bf215546Sopenharmony_ci zink_batch_reference_program(&ctx->batch, &ctx->curr_compute->base); 955bf215546Sopenharmony_ci } 956bf215546Sopenharmony_ci ctx->compute_pipeline_state.module_hash = ctx->curr_compute->curr->hash; 957bf215546Sopenharmony_ci ctx->compute_pipeline_state.module = ctx->curr_compute->curr->shader; 958bf215546Sopenharmony_ci ctx->compute_pipeline_state.final_hash ^= ctx->compute_pipeline_state.module_hash; 959bf215546Sopenharmony_ci if (ctx->compute_pipeline_state.key.base.nonseamless_cube_mask) 960bf215546Sopenharmony_ci ctx->dirty_shader_stages |= BITFIELD_BIT(PIPE_SHADER_COMPUTE); 961bf215546Sopenharmony_ci } else if (!shader) 962bf215546Sopenharmony_ci ctx->curr_compute = NULL; 963bf215546Sopenharmony_ci ctx->compute_stage = shader; 964bf215546Sopenharmony_ci zink_select_launch_grid(ctx); 965bf215546Sopenharmony_ci } else { 966bf215546Sopenharmony_ci if (ctx->gfx_stages[stage]) 967bf215546Sopenharmony_ci ctx->gfx_hash ^= ctx->gfx_stages[stage]->hash; 968bf215546Sopenharmony_ci ctx->gfx_stages[stage] = shader; 969bf215546Sopenharmony_ci ctx->gfx_dirty = ctx->gfx_stages[PIPE_SHADER_FRAGMENT] && ctx->gfx_stages[PIPE_SHADER_VERTEX]; 970bf215546Sopenharmony_ci ctx->gfx_pipeline_state.modules_changed = true; 971bf215546Sopenharmony_ci if (shader) { 972bf215546Sopenharmony_ci ctx->shader_stages |= BITFIELD_BIT(stage); 973bf215546Sopenharmony_ci ctx->gfx_hash ^= ctx->gfx_stages[stage]->hash; 974bf215546Sopenharmony_ci } else { 975bf215546Sopenharmony_ci ctx->gfx_pipeline_state.modules[stage] = VK_NULL_HANDLE; 976bf215546Sopenharmony_ci if (ctx->curr_program) 977bf215546Sopenharmony_ci ctx->gfx_pipeline_state.final_hash ^= ctx->curr_program->last_variant_hash; 978bf215546Sopenharmony_ci ctx->curr_program = NULL; 979bf215546Sopenharmony_ci ctx->shader_stages &= ~BITFIELD_BIT(stage); 980bf215546Sopenharmony_ci } 981bf215546Sopenharmony_ci } 982bf215546Sopenharmony_ci} 983bf215546Sopenharmony_ci 984bf215546Sopenharmony_cistatic void 985bf215546Sopenharmony_cibind_last_vertex_stage(struct zink_context *ctx) 986bf215546Sopenharmony_ci{ 987bf215546Sopenharmony_ci enum pipe_shader_type old = ctx->last_vertex_stage ? pipe_shader_type_from_mesa(ctx->last_vertex_stage->nir->info.stage) : PIPE_SHADER_TYPES; 988bf215546Sopenharmony_ci if (ctx->gfx_stages[PIPE_SHADER_GEOMETRY]) 989bf215546Sopenharmony_ci ctx->last_vertex_stage = ctx->gfx_stages[PIPE_SHADER_GEOMETRY]; 990bf215546Sopenharmony_ci else if (ctx->gfx_stages[PIPE_SHADER_TESS_EVAL]) 991bf215546Sopenharmony_ci ctx->last_vertex_stage = ctx->gfx_stages[PIPE_SHADER_TESS_EVAL]; 992bf215546Sopenharmony_ci else 993bf215546Sopenharmony_ci ctx->last_vertex_stage = ctx->gfx_stages[PIPE_SHADER_VERTEX]; 994bf215546Sopenharmony_ci enum pipe_shader_type current = ctx->last_vertex_stage ? pipe_shader_type_from_mesa(ctx->last_vertex_stage->nir->info.stage) : PIPE_SHADER_VERTEX; 995bf215546Sopenharmony_ci if (old != current) { 996bf215546Sopenharmony_ci if (old != PIPE_SHADER_TYPES) { 997bf215546Sopenharmony_ci memset(&ctx->gfx_pipeline_state.shader_keys.key[old].key.vs_base, 0, sizeof(struct zink_vs_key_base)); 998bf215546Sopenharmony_ci ctx->dirty_shader_stages |= BITFIELD_BIT(old); 999bf215546Sopenharmony_ci } else { 1000bf215546Sopenharmony_ci /* always unset vertex shader values when changing to a non-vs last stage */ 1001bf215546Sopenharmony_ci memset(&ctx->gfx_pipeline_state.shader_keys.key[PIPE_SHADER_VERTEX].key.vs_base, 0, sizeof(struct zink_vs_key_base)); 1002bf215546Sopenharmony_ci } 1003bf215546Sopenharmony_ci 1004bf215546Sopenharmony_ci unsigned num_viewports = ctx->vp_state.num_viewports; 1005bf215546Sopenharmony_ci struct zink_screen *screen = zink_screen(ctx->base.screen); 1006bf215546Sopenharmony_ci /* number of enabled viewports is based on whether last vertex stage writes viewport index */ 1007bf215546Sopenharmony_ci if (ctx->last_vertex_stage) { 1008bf215546Sopenharmony_ci if (ctx->last_vertex_stage->nir->info.outputs_written & (VARYING_BIT_VIEWPORT | VARYING_BIT_VIEWPORT_MASK)) 1009bf215546Sopenharmony_ci ctx->vp_state.num_viewports = MIN2(screen->info.props.limits.maxViewports, PIPE_MAX_VIEWPORTS); 1010bf215546Sopenharmony_ci else 1011bf215546Sopenharmony_ci ctx->vp_state.num_viewports = 1; 1012bf215546Sopenharmony_ci } else { 1013bf215546Sopenharmony_ci ctx->vp_state.num_viewports = 1; 1014bf215546Sopenharmony_ci } 1015bf215546Sopenharmony_ci ctx->vp_state_changed |= num_viewports != ctx->vp_state.num_viewports; 1016bf215546Sopenharmony_ci if (!screen->info.have_EXT_extended_dynamic_state) { 1017bf215546Sopenharmony_ci if (ctx->gfx_pipeline_state.dyn_state1.num_viewports != ctx->vp_state.num_viewports) 1018bf215546Sopenharmony_ci ctx->gfx_pipeline_state.dirty = true; 1019bf215546Sopenharmony_ci ctx->gfx_pipeline_state.dyn_state1.num_viewports = ctx->vp_state.num_viewports; 1020bf215546Sopenharmony_ci } 1021bf215546Sopenharmony_ci ctx->last_vertex_stage_dirty = true; 1022bf215546Sopenharmony_ci } 1023bf215546Sopenharmony_ci} 1024bf215546Sopenharmony_ci 1025bf215546Sopenharmony_cistatic void 1026bf215546Sopenharmony_cizink_bind_vs_state(struct pipe_context *pctx, 1027bf215546Sopenharmony_ci void *cso) 1028bf215546Sopenharmony_ci{ 1029bf215546Sopenharmony_ci struct zink_context *ctx = zink_context(pctx); 1030bf215546Sopenharmony_ci if (!cso && !ctx->gfx_stages[PIPE_SHADER_VERTEX]) 1031bf215546Sopenharmony_ci return; 1032bf215546Sopenharmony_ci bind_stage(ctx, PIPE_SHADER_VERTEX, cso); 1033bf215546Sopenharmony_ci bind_last_vertex_stage(ctx); 1034bf215546Sopenharmony_ci if (cso) { 1035bf215546Sopenharmony_ci struct zink_shader *zs = cso; 1036bf215546Sopenharmony_ci ctx->shader_reads_drawid = BITSET_TEST(zs->nir->info.system_values_read, SYSTEM_VALUE_DRAW_ID); 1037bf215546Sopenharmony_ci ctx->shader_reads_basevertex = BITSET_TEST(zs->nir->info.system_values_read, SYSTEM_VALUE_BASE_VERTEX); 1038bf215546Sopenharmony_ci } else { 1039bf215546Sopenharmony_ci ctx->shader_reads_drawid = false; 1040bf215546Sopenharmony_ci ctx->shader_reads_basevertex = false; 1041bf215546Sopenharmony_ci } 1042bf215546Sopenharmony_ci} 1043bf215546Sopenharmony_ci 1044bf215546Sopenharmony_ci/* if gl_SampleMask[] is written to, we have to ensure that we get a shader with the same sample count: 1045bf215546Sopenharmony_ci * in GL, samples==1 means ignore gl_SampleMask[] 1046bf215546Sopenharmony_ci * in VK, gl_SampleMask[] is never ignored 1047bf215546Sopenharmony_ci */ 1048bf215546Sopenharmony_civoid 1049bf215546Sopenharmony_cizink_update_fs_key_samples(struct zink_context *ctx) 1050bf215546Sopenharmony_ci{ 1051bf215546Sopenharmony_ci if (!ctx->gfx_stages[PIPE_SHADER_FRAGMENT]) 1052bf215546Sopenharmony_ci return; 1053bf215546Sopenharmony_ci nir_shader *nir = ctx->gfx_stages[PIPE_SHADER_FRAGMENT]->nir; 1054bf215546Sopenharmony_ci if (nir->info.outputs_written & (1 << FRAG_RESULT_SAMPLE_MASK)) { 1055bf215546Sopenharmony_ci bool samples = zink_get_fs_key(ctx)->samples; 1056bf215546Sopenharmony_ci if (samples != (ctx->fb_state.samples > 1)) 1057bf215546Sopenharmony_ci zink_set_fs_key(ctx)->samples = ctx->fb_state.samples > 1; 1058bf215546Sopenharmony_ci } 1059bf215546Sopenharmony_ci} 1060bf215546Sopenharmony_ci 1061bf215546Sopenharmony_ci/* if gl_SampleMask[] is written to, we have to ensure that we get a shader with the same sample count: 1062bf215546Sopenharmony_ci * in GL, samples==1 means ignore gl_SampleMask[] 1063bf215546Sopenharmony_ci * in VK, gl_SampleMask[] is never ignored 1064bf215546Sopenharmony_ci */ 1065bf215546Sopenharmony_civoid 1066bf215546Sopenharmony_cizink_update_fs_key_samples(struct zink_context *ctx) 1067bf215546Sopenharmony_ci{ 1068bf215546Sopenharmony_ci if (!ctx->gfx_stages[PIPE_SHADER_FRAGMENT]) 1069bf215546Sopenharmony_ci return; 1070bf215546Sopenharmony_ci nir_shader *nir = ctx->gfx_stages[PIPE_SHADER_FRAGMENT]->nir; 1071bf215546Sopenharmony_ci if (nir->info.outputs_written & (1 << FRAG_RESULT_SAMPLE_MASK)) { 1072bf215546Sopenharmony_ci bool samples = zink_get_fs_key(ctx)->samples; 1073bf215546Sopenharmony_ci if (samples != (ctx->fb_state.samples > 1)) 1074bf215546Sopenharmony_ci zink_set_fs_key(ctx)->samples = ctx->fb_state.samples > 1; 1075bf215546Sopenharmony_ci } 1076bf215546Sopenharmony_ci} 1077bf215546Sopenharmony_ci 1078bf215546Sopenharmony_cistatic void 1079bf215546Sopenharmony_cizink_bind_fs_state(struct pipe_context *pctx, 1080bf215546Sopenharmony_ci void *cso) 1081bf215546Sopenharmony_ci{ 1082bf215546Sopenharmony_ci struct zink_context *ctx = zink_context(pctx); 1083bf215546Sopenharmony_ci if (!cso && !ctx->gfx_stages[PIPE_SHADER_FRAGMENT]) 1084bf215546Sopenharmony_ci return; 1085bf215546Sopenharmony_ci bind_stage(ctx, PIPE_SHADER_FRAGMENT, cso); 1086bf215546Sopenharmony_ci ctx->fbfetch_outputs = 0; 1087bf215546Sopenharmony_ci if (cso) { 1088bf215546Sopenharmony_ci nir_shader *nir = ctx->gfx_stages[PIPE_SHADER_FRAGMENT]->nir; 1089bf215546Sopenharmony_ci if (nir->info.fs.uses_fbfetch_output) { 1090bf215546Sopenharmony_ci nir_foreach_shader_out_variable(var, ctx->gfx_stages[PIPE_SHADER_FRAGMENT]->nir) { 1091bf215546Sopenharmony_ci if (var->data.fb_fetch_output) 1092bf215546Sopenharmony_ci ctx->fbfetch_outputs |= BITFIELD_BIT(var->data.location - FRAG_RESULT_DATA0); 1093bf215546Sopenharmony_ci } 1094bf215546Sopenharmony_ci } 1095bf215546Sopenharmony_ci zink_update_fs_key_samples(ctx); 1096bf215546Sopenharmony_ci } 1097bf215546Sopenharmony_ci zink_update_fbfetch(ctx); 1098bf215546Sopenharmony_ci} 1099bf215546Sopenharmony_ci 1100bf215546Sopenharmony_cistatic void 1101bf215546Sopenharmony_cizink_bind_gs_state(struct pipe_context *pctx, 1102bf215546Sopenharmony_ci void *cso) 1103bf215546Sopenharmony_ci{ 1104bf215546Sopenharmony_ci struct zink_context *ctx = zink_context(pctx); 1105bf215546Sopenharmony_ci if (!cso && !ctx->gfx_stages[PIPE_SHADER_GEOMETRY]) 1106bf215546Sopenharmony_ci return; 1107bf215546Sopenharmony_ci bool had_points = ctx->gfx_stages[PIPE_SHADER_GEOMETRY] ? ctx->gfx_stages[PIPE_SHADER_GEOMETRY]->nir->info.gs.output_primitive == SHADER_PRIM_POINTS : false; 1108bf215546Sopenharmony_ci bind_stage(ctx, PIPE_SHADER_GEOMETRY, cso); 1109bf215546Sopenharmony_ci bind_last_vertex_stage(ctx); 1110bf215546Sopenharmony_ci if (cso) { 1111bf215546Sopenharmony_ci if (!had_points && ctx->last_vertex_stage->nir->info.gs.output_primitive == SHADER_PRIM_POINTS) 1112bf215546Sopenharmony_ci ctx->gfx_pipeline_state.has_points++; 1113bf215546Sopenharmony_ci } else { 1114bf215546Sopenharmony_ci if (had_points) 1115bf215546Sopenharmony_ci ctx->gfx_pipeline_state.has_points--; 1116bf215546Sopenharmony_ci } 1117bf215546Sopenharmony_ci} 1118bf215546Sopenharmony_ci 1119bf215546Sopenharmony_cistatic void 1120bf215546Sopenharmony_cizink_bind_tcs_state(struct pipe_context *pctx, 1121bf215546Sopenharmony_ci void *cso) 1122bf215546Sopenharmony_ci{ 1123bf215546Sopenharmony_ci bind_stage(zink_context(pctx), PIPE_SHADER_TESS_CTRL, cso); 1124bf215546Sopenharmony_ci} 1125bf215546Sopenharmony_ci 1126bf215546Sopenharmony_cistatic void 1127bf215546Sopenharmony_cizink_bind_tes_state(struct pipe_context *pctx, 1128bf215546Sopenharmony_ci void *cso) 1129bf215546Sopenharmony_ci{ 1130bf215546Sopenharmony_ci struct zink_context *ctx = zink_context(pctx); 1131bf215546Sopenharmony_ci if (!cso && !ctx->gfx_stages[PIPE_SHADER_TESS_EVAL]) 1132bf215546Sopenharmony_ci return; 1133bf215546Sopenharmony_ci if (!!ctx->gfx_stages[PIPE_SHADER_TESS_EVAL] != !!cso) { 1134bf215546Sopenharmony_ci if (!cso) { 1135bf215546Sopenharmony_ci /* if unsetting a TESS that uses a generated TCS, ensure the TCS is unset */ 1136bf215546Sopenharmony_ci if (ctx->gfx_stages[PIPE_SHADER_TESS_EVAL]->generated) 1137bf215546Sopenharmony_ci ctx->gfx_stages[PIPE_SHADER_TESS_CTRL] = NULL; 1138bf215546Sopenharmony_ci } 1139bf215546Sopenharmony_ci } 1140bf215546Sopenharmony_ci bind_stage(ctx, PIPE_SHADER_TESS_EVAL, cso); 1141bf215546Sopenharmony_ci bind_last_vertex_stage(ctx); 1142bf215546Sopenharmony_ci} 1143bf215546Sopenharmony_ci 1144bf215546Sopenharmony_cistatic void * 1145bf215546Sopenharmony_cizink_create_cs_state(struct pipe_context *pctx, 1146bf215546Sopenharmony_ci const struct pipe_compute_state *shader) 1147bf215546Sopenharmony_ci{ 1148bf215546Sopenharmony_ci struct nir_shader *nir; 1149bf215546Sopenharmony_ci if (shader->ir_type != PIPE_SHADER_IR_NIR) 1150bf215546Sopenharmony_ci nir = zink_tgsi_to_nir(pctx->screen, shader->prog); 1151bf215546Sopenharmony_ci else 1152bf215546Sopenharmony_ci nir = (struct nir_shader *)shader->prog; 1153bf215546Sopenharmony_ci 1154bf215546Sopenharmony_ci return zink_shader_create(zink_screen(pctx->screen), nir, NULL); 1155bf215546Sopenharmony_ci} 1156bf215546Sopenharmony_ci 1157bf215546Sopenharmony_cistatic void 1158bf215546Sopenharmony_cizink_bind_cs_state(struct pipe_context *pctx, 1159bf215546Sopenharmony_ci void *cso) 1160bf215546Sopenharmony_ci{ 1161bf215546Sopenharmony_ci bind_stage(zink_context(pctx), PIPE_SHADER_COMPUTE, cso); 1162bf215546Sopenharmony_ci} 1163bf215546Sopenharmony_ci 1164bf215546Sopenharmony_civoid 1165bf215546Sopenharmony_cizink_delete_shader_state(struct pipe_context *pctx, void *cso) 1166bf215546Sopenharmony_ci{ 1167bf215546Sopenharmony_ci zink_shader_free(zink_context(pctx), cso); 1168bf215546Sopenharmony_ci} 1169bf215546Sopenharmony_ci 1170bf215546Sopenharmony_civoid * 1171bf215546Sopenharmony_cizink_create_gfx_shader_state(struct pipe_context *pctx, const struct pipe_shader_state *shader) 1172bf215546Sopenharmony_ci{ 1173bf215546Sopenharmony_ci nir_shader *nir; 1174bf215546Sopenharmony_ci if (shader->type != PIPE_SHADER_IR_NIR) 1175bf215546Sopenharmony_ci nir = zink_tgsi_to_nir(pctx->screen, shader->tokens); 1176bf215546Sopenharmony_ci else 1177bf215546Sopenharmony_ci nir = (struct nir_shader *)shader->ir.nir; 1178bf215546Sopenharmony_ci 1179bf215546Sopenharmony_ci return zink_shader_create(zink_screen(pctx->screen), nir, &shader->stream_output); 1180bf215546Sopenharmony_ci} 1181bf215546Sopenharmony_ci 1182bf215546Sopenharmony_cistatic void 1183bf215546Sopenharmony_cizink_delete_cached_shader_state(struct pipe_context *pctx, void *cso) 1184bf215546Sopenharmony_ci{ 1185bf215546Sopenharmony_ci struct zink_screen *screen = zink_screen(pctx->screen); 1186bf215546Sopenharmony_ci util_shader_reference(pctx, &screen->shaders, &cso, NULL); 1187bf215546Sopenharmony_ci} 1188bf215546Sopenharmony_ci 1189bf215546Sopenharmony_cistatic void * 1190bf215546Sopenharmony_cizink_create_cached_shader_state(struct pipe_context *pctx, const struct pipe_shader_state *shader) 1191bf215546Sopenharmony_ci{ 1192bf215546Sopenharmony_ci bool cache_hit; 1193bf215546Sopenharmony_ci struct zink_screen *screen = zink_screen(pctx->screen); 1194bf215546Sopenharmony_ci return util_live_shader_cache_get(pctx, &screen->shaders, shader, &cache_hit); 1195bf215546Sopenharmony_ci} 1196bf215546Sopenharmony_ci 1197bf215546Sopenharmony_civoid 1198bf215546Sopenharmony_cizink_program_init(struct zink_context *ctx) 1199bf215546Sopenharmony_ci{ 1200bf215546Sopenharmony_ci ctx->base.create_vs_state = zink_create_cached_shader_state; 1201bf215546Sopenharmony_ci ctx->base.bind_vs_state = zink_bind_vs_state; 1202bf215546Sopenharmony_ci ctx->base.delete_vs_state = zink_delete_cached_shader_state; 1203bf215546Sopenharmony_ci 1204bf215546Sopenharmony_ci ctx->base.create_fs_state = zink_create_cached_shader_state; 1205bf215546Sopenharmony_ci ctx->base.bind_fs_state = zink_bind_fs_state; 1206bf215546Sopenharmony_ci ctx->base.delete_fs_state = zink_delete_cached_shader_state; 1207bf215546Sopenharmony_ci 1208bf215546Sopenharmony_ci ctx->base.create_gs_state = zink_create_cached_shader_state; 1209bf215546Sopenharmony_ci ctx->base.bind_gs_state = zink_bind_gs_state; 1210bf215546Sopenharmony_ci ctx->base.delete_gs_state = zink_delete_cached_shader_state; 1211bf215546Sopenharmony_ci 1212bf215546Sopenharmony_ci ctx->base.create_tcs_state = zink_create_cached_shader_state; 1213bf215546Sopenharmony_ci ctx->base.bind_tcs_state = zink_bind_tcs_state; 1214bf215546Sopenharmony_ci ctx->base.delete_tcs_state = zink_delete_cached_shader_state; 1215bf215546Sopenharmony_ci 1216bf215546Sopenharmony_ci ctx->base.create_tes_state = zink_create_cached_shader_state; 1217bf215546Sopenharmony_ci ctx->base.bind_tes_state = zink_bind_tes_state; 1218bf215546Sopenharmony_ci ctx->base.delete_tes_state = zink_delete_cached_shader_state; 1219bf215546Sopenharmony_ci 1220bf215546Sopenharmony_ci ctx->base.create_compute_state = zink_create_cs_state; 1221bf215546Sopenharmony_ci ctx->base.bind_compute_state = zink_bind_cs_state; 1222bf215546Sopenharmony_ci ctx->base.delete_compute_state = zink_delete_shader_state; 1223bf215546Sopenharmony_ci} 1224bf215546Sopenharmony_ci 1225bf215546Sopenharmony_cibool 1226bf215546Sopenharmony_cizink_set_rasterizer_discard(struct zink_context *ctx, bool disable) 1227bf215546Sopenharmony_ci{ 1228bf215546Sopenharmony_ci bool value = disable ? false : (ctx->rast_state ? ctx->rast_state->base.rasterizer_discard : false); 1229bf215546Sopenharmony_ci bool changed = ctx->gfx_pipeline_state.dyn_state2.rasterizer_discard != value; 1230bf215546Sopenharmony_ci ctx->gfx_pipeline_state.dyn_state2.rasterizer_discard = value; 1231bf215546Sopenharmony_ci if (!changed) 1232bf215546Sopenharmony_ci return false; 1233bf215546Sopenharmony_ci if (!zink_screen(ctx->base.screen)->info.have_EXT_extended_dynamic_state2) 1234bf215546Sopenharmony_ci ctx->gfx_pipeline_state.dirty |= true; 1235bf215546Sopenharmony_ci ctx->rasterizer_discard_changed = true; 1236bf215546Sopenharmony_ci return true; 1237bf215546Sopenharmony_ci} 1238