Path: blob/21.2-virgl/src/gallium/drivers/zink/zink_program.c
4570 views
/*1* Copyright 2018 Collabora Ltd.2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* on the rights to use, copy, modify, merge, publish, distribute, sub7* license, and/or sell copies of the Software, and to permit persons to whom8* the Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL17* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,18* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR19* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE20* USE OR OTHER DEALINGS IN THE SOFTWARE.21*/2223#include "zink_program.h"2425#include "zink_compiler.h"26#include "zink_context.h"27#include "zink_descriptors.h"28#include "zink_render_pass.h"29#include "zink_resource.h"30#include "zink_screen.h"31#include "zink_state.h"3233#include "util/hash_table.h"34#include "util/set.h"35#include "util/u_debug.h"36#include "util/u_memory.h"37#include "tgsi/tgsi_from_mesa.h"3839/* for pipeline cache */40#define XXH_INLINE_ALL41#include "util/xxhash.h"4243struct gfx_pipeline_cache_entry {44struct zink_gfx_pipeline_state state;45VkPipeline pipeline;46};4748struct compute_pipeline_cache_entry {49struct zink_compute_pipeline_state state;50VkPipeline pipeline;51};5253void54debug_describe_zink_gfx_program(char *buf, const struct zink_gfx_program *ptr)55{56sprintf(buf, "zink_gfx_program");57}5859void60debug_describe_zink_compute_program(char *buf, const struct zink_compute_program *ptr)61{62sprintf(buf, "zink_compute_program");63}6465/* copied from iris */66struct keybox {67uint16_t size;68gl_shader_stage stage;69uint8_t data[0];70};7172static struct keybox *73make_keybox(void *mem_ctx, gl_shader_stage stage, const void *key, uint32_t key_size, void *base, uint32_t base_size)74{75struct keybox *keybox =76ralloc_size(mem_ctx, sizeof(struct keybox) + key_size + base_size);7778keybox->stage = stage;79keybox->size = key_size + base_size;80memcpy(keybox->data, key, key_size);81if (base_size)82memcpy(&keybox->data[key_size], base, base_size);83return keybox;84}8586static uint32_t87keybox_hash(const void *void_key)88{89const struct keybox *key = void_key;90return _mesa_hash_data(&key->stage, key->size + sizeof(key->stage));91}9293static bool94keybox_equals(const void *void_a, const void *void_b)95{96const struct keybox *a = void_a, *b = void_b;97if (a->size != b->size)98return false;99100return memcmp(a->data, b->data, a->size) == 0;101}102103static void104shader_key_vs_gen(struct zink_context *ctx, struct zink_shader *zs,105struct zink_shader *shaders[ZINK_SHADER_COUNT], struct zink_shader_key *key)106{107struct zink_vs_key *vs_key = &key->key.vs;108key->size = sizeof(struct zink_vs_key);109110vs_key->clip_halfz = ctx->rast_state->base.clip_halfz;111switch (zs->nir->info.stage) {112case MESA_SHADER_VERTEX:113vs_key->last_vertex_stage = !shaders[PIPE_SHADER_TESS_EVAL] && !shaders[PIPE_SHADER_GEOMETRY];114vs_key->push_drawid = ctx->drawid_broken;115break;116case MESA_SHADER_TESS_EVAL:117vs_key->last_vertex_stage = !shaders[PIPE_SHADER_GEOMETRY];118break;119case MESA_SHADER_GEOMETRY:120vs_key->last_vertex_stage = true;121break;122default:123unreachable("impossible case");124}125}126127static void128shader_key_fs_gen(struct zink_context *ctx, struct zink_shader *zs,129struct zink_shader *shaders[ZINK_SHADER_COUNT], struct zink_shader_key *key)130{131struct zink_screen *screen = zink_screen(ctx->base.screen);132struct zink_fs_key *fs_key = &key->key.fs;133key->size = sizeof(struct zink_fs_key);134135/* if gl_SampleMask[] is written to, we have to ensure that we get a shader with the same sample count:136* in GL, rast_samples==1 means ignore gl_SampleMask[]137* in VK, gl_SampleMask[] is never ignored138*/139if (zs->nir->info.outputs_written & (1 << FRAG_RESULT_SAMPLE_MASK))140fs_key->samples = !!ctx->fb_state.samples;141fs_key->force_dual_color_blend = screen->driconf.dual_color_blend_by_location &&142ctx->gfx_pipeline_state.blend_state->dual_src_blend &&143ctx->gfx_pipeline_state.blend_state->attachments[1].blendEnable;144if (((shaders[PIPE_SHADER_GEOMETRY] && shaders[PIPE_SHADER_GEOMETRY]->nir->info.gs.output_primitive == GL_POINTS) ||145ctx->gfx_prim_mode == PIPE_PRIM_POINTS) && ctx->rast_state->base.point_quad_rasterization && ctx->rast_state->base.sprite_coord_enable) {146fs_key->coord_replace_bits = ctx->rast_state->base.sprite_coord_enable;147fs_key->coord_replace_yinvert = !!ctx->rast_state->base.sprite_coord_mode;148}149}150151static void152shader_key_tcs_gen(struct zink_context *ctx, struct zink_shader *zs,153struct zink_shader *shaders[ZINK_SHADER_COUNT], struct zink_shader_key *key)154{155struct zink_tcs_key *tcs_key = &key->key.tcs;156key->size = sizeof(struct zink_tcs_key);157158tcs_key->vertices_per_patch = ctx->gfx_pipeline_state.vertices_per_patch;159tcs_key->vs_outputs_written = shaders[PIPE_SHADER_VERTEX]->nir->info.outputs_written;160}161162typedef void (*zink_shader_key_gen)(struct zink_context *ctx, struct zink_shader *zs,163struct zink_shader *shaders[ZINK_SHADER_COUNT],164struct zink_shader_key *key);165static zink_shader_key_gen shader_key_vtbl[] =166{167[MESA_SHADER_VERTEX] = shader_key_vs_gen,168[MESA_SHADER_TESS_CTRL] = shader_key_tcs_gen,169/* reusing vs key for now since we're only using clip_halfz */170[MESA_SHADER_TESS_EVAL] = shader_key_vs_gen,171[MESA_SHADER_GEOMETRY] = shader_key_vs_gen,172[MESA_SHADER_FRAGMENT] = shader_key_fs_gen,173};174175/* return pointer to make function reusable */176static inline struct zink_shader_module **177get_default_shader_module_ptr(struct zink_gfx_program *prog, struct zink_shader *zs, struct zink_shader_key *key)178{179if (zs->nir->info.stage == MESA_SHADER_VERTEX ||180zs->nir->info.stage == MESA_SHADER_TESS_EVAL) {181/* no streamout or halfz */182if (!zink_vs_key(key)->last_vertex_stage)183return &prog->default_variants[zs->nir->info.stage][1];184}185return &prog->default_variants[zs->nir->info.stage][0];186}187188static struct zink_shader_module *189get_shader_module_for_stage(struct zink_context *ctx, struct zink_shader *zs, struct zink_gfx_program *prog)190{191gl_shader_stage stage = zs->nir->info.stage;192enum pipe_shader_type pstage = pipe_shader_type_from_mesa(stage);193struct zink_shader_key key = {0};194VkShaderModule mod;195struct zink_shader_module *zm;196struct zink_shader_module **default_zm = NULL;197struct keybox *keybox;198uint32_t hash;199unsigned base_size = 0;200201shader_key_vtbl[stage](ctx, zs, ctx->gfx_stages, &key);202/* this is default variant if there is no default or it matches the default */203if (prog->default_variant_key[pstage]) {204const struct keybox *tmp = prog->default_variant_key[pstage];205/* if comparing against the existing default, use the base variant key size since206* we're only checking the stage-specific data207*/208key.is_default_variant = !memcmp(tmp->data, &key, key.size);209} else210key.is_default_variant = true;211212if (zs->nir->info.num_inlinable_uniforms &&213ctx->inlinable_uniforms_valid_mask & BITFIELD64_BIT(pstage)) {214key.inline_uniforms = true;215memcpy(key.base.inlined_uniform_values,216ctx->inlinable_uniforms[pstage],217zs->nir->info.num_inlinable_uniforms * 4);218base_size = zs->nir->info.num_inlinable_uniforms * sizeof(uint32_t);219key.is_default_variant = false;220}221if (key.is_default_variant) {222default_zm = get_default_shader_module_ptr(prog, zs, &key);223if (*default_zm)224return *default_zm;225}226keybox = make_keybox(prog, stage, &key, key.size, &key.base, base_size);227hash = keybox_hash(keybox);228struct hash_entry *entry = _mesa_hash_table_search_pre_hashed(&prog->base.shader_cache[pstage],229hash, keybox);230231if (entry) {232ralloc_free(keybox);233zm = entry->data;234} else {235zm = CALLOC_STRUCT(zink_shader_module);236if (!zm) {237ralloc_free(keybox);238return NULL;239}240mod = zink_shader_compile(zink_screen(ctx->base.screen), zs, prog->nir[stage], &key);241if (!mod) {242ralloc_free(keybox);243FREE(zm);244return NULL;245}246zm->shader = mod;247248_mesa_hash_table_insert_pre_hashed(&prog->base.shader_cache[pstage], hash, keybox, zm);249if (key.is_default_variant) {250/* previously returned */251*default_zm = zm;252zm->default_variant = true;253prog->default_variant_key[pstage] = keybox;254}255}256return zm;257}258259static void260zink_destroy_shader_module(struct zink_screen *screen, struct zink_shader_module *zm)261{262vkDestroyShaderModule(screen->dev, zm->shader, NULL);263free(zm);264}265266static void267destroy_shader_cache(struct zink_screen *screen, struct hash_table *sc)268{269hash_table_foreach(sc, entry) {270struct zink_shader_module *zm = entry->data;271zink_destroy_shader_module(screen, zm);272}273}274275static void276update_shader_modules(struct zink_context *ctx, struct zink_shader *stages[ZINK_SHADER_COUNT], struct zink_gfx_program *prog, bool disallow_reuse)277{278struct zink_shader *dirty[ZINK_SHADER_COUNT] = {NULL};279280unsigned gfx_bits = u_bit_consecutive(PIPE_SHADER_VERTEX, 5);281unsigned dirty_shader_stages = ctx->dirty_shader_stages & gfx_bits;282if (!dirty_shader_stages)283return;284/* we need to map pipe_shader_type -> gl_shader_stage so we can ensure that we're compiling285* the shaders in pipeline order and have builtin input/output locations match up after being compacted286*/287while (dirty_shader_stages) {288unsigned type = u_bit_scan(&dirty_shader_stages);289dirty[tgsi_processor_to_shader_stage(type)] = stages[type];290}291292for (int i = 0; i < ZINK_SHADER_COUNT; ++i) {293/* we need to iterate over the stages in pipeline-order here */294enum pipe_shader_type type = pipe_shader_type_from_mesa(i);295assert(type < ZINK_SHADER_COUNT);296if (dirty[i] || (stages[type] && !prog->modules[type])) {297struct zink_shader_module *zm;298zm = get_shader_module_for_stage(ctx, dirty[i] ? dirty[i] : stages[type], prog);299prog->modules[type] = zm;300ctx->gfx_pipeline_state.combined_dirty |= zm->shader != ctx->gfx_pipeline_state.modules[type];301ctx->gfx_pipeline_state.modules[type] = zm->shader;302} else if (!stages[type]) {303ctx->gfx_pipeline_state.combined_dirty |= ctx->gfx_pipeline_state.modules[type] != VK_NULL_HANDLE;304ctx->gfx_pipeline_state.modules[type] = VK_NULL_HANDLE;305}306}307ctx->gfx_pipeline_state.module_hash = _mesa_hash_data(ctx->gfx_pipeline_state.modules, sizeof(ctx->gfx_pipeline_state.modules));308unsigned clean = u_bit_consecutive(PIPE_SHADER_VERTEX, 5);309ctx->dirty_shader_stages &= ~clean;310}311312static uint32_t313hash_gfx_pipeline_state(const void *key)314{315const struct zink_gfx_pipeline_state *state = key;316uint32_t hash = _mesa_hash_data(key, offsetof(struct zink_gfx_pipeline_state, hash));317if (state->have_EXT_extended_dynamic_state)318return hash;319return XXH32(&state->depth_stencil_alpha_state, sizeof(void*), hash);320}321322static bool323equals_gfx_pipeline_state(const void *a, const void *b)324{325const struct zink_gfx_pipeline_state *sa = a;326const struct zink_gfx_pipeline_state *sb = b;327if (!sa->have_EXT_extended_dynamic_state) {328if (sa->vertex_buffers_enabled_mask != sb->vertex_buffers_enabled_mask)329return false;330/* if we don't have dynamic states, we have to hash the enabled vertex buffer bindings */331uint32_t mask_a = sa->vertex_buffers_enabled_mask;332uint32_t mask_b = sb->vertex_buffers_enabled_mask;333while (mask_a || mask_b) {334unsigned idx_a = u_bit_scan(&mask_a);335unsigned idx_b = u_bit_scan(&mask_b);336if (sa->vertex_strides[idx_a] != sb->vertex_strides[idx_b])337return false;338}339if (sa->front_face != sb->front_face)340return false;341if (!!sa->depth_stencil_alpha_state != !!sb->depth_stencil_alpha_state ||342(sa && sb && memcmp(sa->depth_stencil_alpha_state, sb->depth_stencil_alpha_state, sizeof(struct zink_depth_stencil_alpha_hw_state))))343return false;344}345return !memcmp(sa->modules, sb->modules, sizeof(sa->modules)) &&346!memcmp(a, b, offsetof(struct zink_gfx_pipeline_state, hash));347}348349void350zink_update_gfx_program(struct zink_context *ctx, struct zink_gfx_program *prog)351{352update_shader_modules(ctx, ctx->gfx_stages, prog, true);353}354355VkPipelineLayout356zink_pipeline_layout_create(struct zink_screen *screen, struct zink_program *pg)357{358VkPipelineLayoutCreateInfo plci = {0};359plci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;360361plci.pSetLayouts = pg->dsl;362plci.setLayoutCount = pg->num_dsl;363364VkPushConstantRange pcr[2] = {0};365if (pg->is_compute) {366if (((struct zink_compute_program*)pg)->shader->nir->info.stage == MESA_SHADER_KERNEL) {367pcr[0].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;368pcr[0].offset = 0;369pcr[0].size = sizeof(struct zink_cs_push_constant);370plci.pushConstantRangeCount = 1;371}372} else {373pcr[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;374pcr[0].offset = offsetof(struct zink_gfx_push_constant, draw_mode_is_indexed);375pcr[0].size = 2 * sizeof(unsigned);376pcr[1].stageFlags = VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;377pcr[1].offset = offsetof(struct zink_gfx_push_constant, default_inner_level);378pcr[1].size = sizeof(float) * 6;379plci.pushConstantRangeCount = 2;380}381plci.pPushConstantRanges = &pcr[0];382383VkPipelineLayout layout;384if (vkCreatePipelineLayout(screen->dev, &plci, NULL, &layout) != VK_SUCCESS) {385debug_printf("vkCreatePipelineLayout failed!\n");386return VK_NULL_HANDLE;387}388389return layout;390}391392static void393assign_io(struct zink_gfx_program *prog, struct zink_shader *stages[ZINK_SHADER_COUNT])394{395struct zink_shader *shaders[PIPE_SHADER_TYPES];396397/* build array in pipeline order */398for (unsigned i = 0; i < ZINK_SHADER_COUNT; i++)399shaders[tgsi_processor_to_shader_stage(i)] = stages[i];400401for (unsigned i = 0; i < MESA_SHADER_FRAGMENT;) {402nir_shader *producer = shaders[i]->nir;403for (unsigned j = i + 1; j < ZINK_SHADER_COUNT; i++, j++) {404struct zink_shader *consumer = shaders[j];405if (!consumer)406continue;407if (!prog->nir[producer->info.stage])408prog->nir[producer->info.stage] = nir_shader_clone(prog, producer);409if (!prog->nir[j])410prog->nir[j] = nir_shader_clone(prog, consumer->nir);411zink_compiler_assign_io(prog->nir[producer->info.stage], prog->nir[j]);412i = j;413break;414}415}416}417418struct zink_gfx_program *419zink_create_gfx_program(struct zink_context *ctx,420struct zink_shader *stages[ZINK_SHADER_COUNT])421{422struct zink_screen *screen = zink_screen(ctx->base.screen);423struct zink_gfx_program *prog = rzalloc(NULL, struct zink_gfx_program);424if (!prog)425goto fail;426427pipe_reference_init(&prog->base.reference, 1);428429for (int i = 0; i < ZINK_SHADER_COUNT; ++i) {430if (stages[i]) {431_mesa_hash_table_init(&prog->base.shader_cache[i], prog, keybox_hash, keybox_equals);432prog->shaders[i] = stages[i];433prog->stages_present |= BITFIELD_BIT(i);434}435}436if (stages[PIPE_SHADER_TESS_EVAL] && !stages[PIPE_SHADER_TESS_CTRL]) {437prog->shaders[PIPE_SHADER_TESS_EVAL]->generated =438prog->shaders[PIPE_SHADER_TESS_CTRL] =439zink_shader_tcs_create(ctx, stages[PIPE_SHADER_VERTEX]);440_mesa_hash_table_init(&prog->base.shader_cache[PIPE_SHADER_TESS_CTRL], prog, keybox_hash, keybox_equals);441prog->stages_present |= BITFIELD_BIT(PIPE_SHADER_TESS_CTRL);442}443444/* always force shader creation during init */445ctx->dirty_shader_stages |= prog->stages_present;446assign_io(prog, prog->shaders);447448update_shader_modules(ctx, prog->shaders, prog, false);449prog->default_variant_hash = ctx->gfx_pipeline_state.module_hash;450451for (int i = 0; i < ARRAY_SIZE(prog->pipelines); ++i) {452prog->pipelines[i] = _mesa_hash_table_create(NULL,453NULL,454equals_gfx_pipeline_state);455if (!prog->pipelines[i])456goto fail;457}458459if (stages[PIPE_SHADER_GEOMETRY])460prog->last_vertex_stage = stages[PIPE_SHADER_GEOMETRY];461else if (stages[PIPE_SHADER_TESS_EVAL])462prog->last_vertex_stage = stages[PIPE_SHADER_TESS_EVAL];463else464prog->last_vertex_stage = stages[PIPE_SHADER_VERTEX];465466struct mesa_sha1 sctx;467_mesa_sha1_init(&sctx);468for (int i = 0; i < ZINK_SHADER_COUNT; ++i) {469if (prog->modules[i]) {470_mesa_set_add(prog->shaders[i]->programs, prog);471zink_gfx_program_reference(screen, NULL, prog);472_mesa_sha1_update(&sctx, prog->shaders[i]->base.sha1, sizeof(prog->shaders[i]->base.sha1));473}474}475_mesa_sha1_final(&sctx, prog->base.sha1);476p_atomic_dec(&prog->base.reference.count);477478if (!screen->descriptor_program_init(ctx, &prog->base))479goto fail;480481zink_screen_get_pipeline_cache(screen, &prog->base);482return prog;483484fail:485if (prog)486zink_destroy_gfx_program(screen, prog);487return NULL;488}489490static uint32_t491hash_compute_pipeline_state(const void *key)492{493const struct zink_compute_pipeline_state *state = key;494uint32_t hash = _mesa_hash_data(state, offsetof(struct zink_compute_pipeline_state, hash));495if (state->use_local_size)496hash = XXH32(&state->local_size[0], sizeof(state->local_size), hash);497return hash;498}499500void501zink_program_update_compute_pipeline_state(struct zink_context *ctx, struct zink_compute_program *comp, const uint block[3])502{503struct zink_shader *zs = comp->shader;504bool use_local_size = !(zs->nir->info.workgroup_size[0] ||505zs->nir->info.workgroup_size[1] ||506zs->nir->info.workgroup_size[2]);507if (ctx->compute_pipeline_state.use_local_size != use_local_size)508ctx->compute_pipeline_state.dirty = true;509ctx->compute_pipeline_state.use_local_size = use_local_size;510511if (ctx->compute_pipeline_state.use_local_size) {512for (int i = 0; i < ARRAY_SIZE(ctx->compute_pipeline_state.local_size); i++) {513if (ctx->compute_pipeline_state.local_size[i] != block[i])514ctx->compute_pipeline_state.dirty = true;515ctx->compute_pipeline_state.local_size[i] = block[i];516}517} else518ctx->compute_pipeline_state.local_size[0] =519ctx->compute_pipeline_state.local_size[1] =520ctx->compute_pipeline_state.local_size[2] = 0;521}522523static bool524equals_compute_pipeline_state(const void *a, const void *b)525{526return memcmp(a, b, offsetof(struct zink_compute_pipeline_state, hash)) == 0;527}528529struct zink_compute_program *530zink_create_compute_program(struct zink_context *ctx, struct zink_shader *shader)531{532struct zink_screen *screen = zink_screen(ctx->base.screen);533struct zink_compute_program *comp = rzalloc(NULL, struct zink_compute_program);534if (!comp)535goto fail;536537pipe_reference_init(&comp->base.reference, 1);538comp->base.is_compute = true;539/* TODO: cs shader keys placeholder for now */540_mesa_hash_table_init(&comp->base.shader_cache[0], comp, _mesa_hash_pointer, _mesa_key_pointer_equal);541542comp->module = CALLOC_STRUCT(zink_shader_module);543assert(comp->module);544comp->module->shader = zink_shader_compile(screen, shader, shader->nir, NULL);545assert(comp->module->shader);546_mesa_hash_table_insert(&comp->base.shader_cache[0], shader, comp->module);547548ctx->dirty_shader_stages &= ~(1 << PIPE_SHADER_COMPUTE);549550comp->pipelines = _mesa_hash_table_create(NULL, hash_compute_pipeline_state,551equals_compute_pipeline_state);552553_mesa_set_add(shader->programs, comp);554comp->shader = shader;555memcpy(comp->base.sha1, shader->base.sha1, sizeof(shader->base.sha1));556557if (!screen->descriptor_program_init(ctx, &comp->base))558goto fail;559560zink_screen_get_pipeline_cache(screen, &comp->base);561return comp;562563fail:564if (comp)565zink_destroy_compute_program(screen, comp);566return NULL;567}568569uint32_t570zink_program_get_descriptor_usage(struct zink_context *ctx, enum pipe_shader_type stage, enum zink_descriptor_type type)571{572struct zink_shader *zs = NULL;573switch (stage) {574case PIPE_SHADER_VERTEX:575case PIPE_SHADER_TESS_CTRL:576case PIPE_SHADER_TESS_EVAL:577case PIPE_SHADER_GEOMETRY:578case PIPE_SHADER_FRAGMENT:579zs = ctx->gfx_stages[stage];580break;581case PIPE_SHADER_COMPUTE: {582zs = ctx->compute_stage;583break;584}585default:586unreachable("unknown shader type");587}588if (!zs)589return 0;590switch (type) {591case ZINK_DESCRIPTOR_TYPE_UBO:592return zs->ubos_used;593case ZINK_DESCRIPTOR_TYPE_SSBO:594return zs->ssbos_used;595case ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW:596return BITSET_TEST_RANGE(zs->nir->info.textures_used, 0, PIPE_MAX_SAMPLERS - 1);597case ZINK_DESCRIPTOR_TYPE_IMAGE:598return zs->nir->info.images_used;599default:600unreachable("unknown descriptor type!");601}602return 0;603}604605bool606zink_program_descriptor_is_buffer(struct zink_context *ctx, enum pipe_shader_type stage, enum zink_descriptor_type type, unsigned i)607{608struct zink_shader *zs = NULL;609switch (stage) {610case PIPE_SHADER_VERTEX:611case PIPE_SHADER_TESS_CTRL:612case PIPE_SHADER_TESS_EVAL:613case PIPE_SHADER_GEOMETRY:614case PIPE_SHADER_FRAGMENT:615zs = ctx->gfx_stages[stage];616break;617case PIPE_SHADER_COMPUTE: {618zs = ctx->compute_stage;619break;620}621default:622unreachable("unknown shader type");623}624if (!zs)625return false;626return zink_shader_descriptor_is_buffer(zs, type, i);627}628629static unsigned630get_num_bindings(struct zink_shader *zs, enum zink_descriptor_type type)631{632switch (type) {633case ZINK_DESCRIPTOR_TYPE_UBO:634case ZINK_DESCRIPTOR_TYPE_SSBO:635return zs->num_bindings[type];636default:637break;638}639unsigned num_bindings = 0;640for (int i = 0; i < zs->num_bindings[type]; i++)641num_bindings += zs->bindings[type][i].size;642return num_bindings;643}644645unsigned646zink_program_num_bindings_typed(const struct zink_program *pg, enum zink_descriptor_type type, bool is_compute)647{648unsigned num_bindings = 0;649if (is_compute) {650struct zink_compute_program *comp = (void*)pg;651return get_num_bindings(comp->shader, type);652}653struct zink_gfx_program *prog = (void*)pg;654for (unsigned i = 0; i < ZINK_SHADER_COUNT; i++) {655if (prog->shaders[i])656num_bindings += get_num_bindings(prog->shaders[i], type);657}658return num_bindings;659}660661unsigned662zink_program_num_bindings(const struct zink_program *pg, bool is_compute)663{664unsigned num_bindings = 0;665for (unsigned i = 0; i < ZINK_DESCRIPTOR_TYPES; i++)666num_bindings += zink_program_num_bindings_typed(pg, i, is_compute);667return num_bindings;668}669670void671zink_destroy_gfx_program(struct zink_screen *screen,672struct zink_gfx_program *prog)673{674if (prog->base.layout)675vkDestroyPipelineLayout(screen->dev, prog->base.layout, NULL);676677for (int i = 0; i < ZINK_SHADER_COUNT; ++i) {678if (prog->shaders[i]) {679_mesa_set_remove_key(prog->shaders[i]->programs, prog);680prog->shaders[i] = NULL;681destroy_shader_cache(screen, &prog->base.shader_cache[i]);682}683}684685for (int i = 0; i < ARRAY_SIZE(prog->pipelines); ++i) {686hash_table_foreach(prog->pipelines[i], entry) {687struct gfx_pipeline_cache_entry *pc_entry = entry->data;688689vkDestroyPipeline(screen->dev, pc_entry->pipeline, NULL);690free(pc_entry);691}692_mesa_hash_table_destroy(prog->pipelines[i], NULL);693}694if (prog->base.pipeline_cache)695vkDestroyPipelineCache(screen->dev, prog->base.pipeline_cache, NULL);696screen->descriptor_program_deinit(screen, &prog->base);697698ralloc_free(prog);699}700701void702zink_destroy_compute_program(struct zink_screen *screen,703struct zink_compute_program *comp)704{705if (comp->base.layout)706vkDestroyPipelineLayout(screen->dev, comp->base.layout, NULL);707708if (comp->shader)709_mesa_set_remove_key(comp->shader->programs, comp);710711hash_table_foreach(comp->pipelines, entry) {712struct compute_pipeline_cache_entry *pc_entry = entry->data;713714vkDestroyPipeline(screen->dev, pc_entry->pipeline, NULL);715free(pc_entry);716}717_mesa_hash_table_destroy(comp->pipelines, NULL);718destroy_shader_cache(screen, &comp->base.shader_cache[0]);719if (comp->base.pipeline_cache)720vkDestroyPipelineCache(screen->dev, comp->base.pipeline_cache, NULL);721screen->descriptor_program_deinit(screen, &comp->base);722723ralloc_free(comp);724}725726static VkPrimitiveTopology727primitive_topology(enum pipe_prim_type mode)728{729switch (mode) {730case PIPE_PRIM_POINTS:731return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;732733case PIPE_PRIM_LINES:734return VK_PRIMITIVE_TOPOLOGY_LINE_LIST;735736case PIPE_PRIM_LINE_STRIP:737return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;738739case PIPE_PRIM_TRIANGLES:740return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;741742case PIPE_PRIM_TRIANGLE_STRIP:743return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;744745case PIPE_PRIM_TRIANGLE_FAN:746return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN;747748case PIPE_PRIM_LINE_STRIP_ADJACENCY:749return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY;750751case PIPE_PRIM_LINES_ADJACENCY:752return VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY;753754case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:755return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY;756757case PIPE_PRIM_TRIANGLES_ADJACENCY:758return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY;759760case PIPE_PRIM_PATCHES:761return VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;762763default:764unreachable("unexpected enum pipe_prim_type");765}766}767768VkPipeline769zink_get_gfx_pipeline(struct zink_context *ctx,770struct zink_gfx_program *prog,771struct zink_gfx_pipeline_state *state,772enum pipe_prim_type mode)773{774if (!state->dirty && !state->combined_dirty && !state->vertex_state_dirty && mode == state->mode)775return state->pipeline;776777struct zink_screen *screen = zink_screen(ctx->base.screen);778VkPrimitiveTopology vkmode = primitive_topology(mode);779assert(vkmode <= ARRAY_SIZE(prog->pipelines));780781struct hash_entry *entry = NULL;782783if (state->dirty) {784state->vertex_state_dirty = state->combined_dirty = true;785state->hash = hash_gfx_pipeline_state(state);786state->dirty = false;787}788if (state->combined_dirty) {789state->vertex_state_dirty = true;790state->combined_hash = XXH32(&state->module_hash, sizeof(uint32_t), state->hash);791state->combined_dirty = false;792}793if (state->vertex_state_dirty) {794uint32_t hash = state->combined_hash;795if (!state->have_EXT_extended_dynamic_state) {796/* if we don't have dynamic states, we have to hash the enabled vertex buffer bindings */797uint32_t vertex_buffers_enabled_mask = state->vertex_buffers_enabled_mask;798hash = XXH32(&vertex_buffers_enabled_mask, sizeof(uint32_t), hash);799800for (unsigned i = 0; i < state->element_state->num_bindings; i++) {801struct pipe_vertex_buffer *vb = ctx->vertex_buffers + ctx->element_state->binding_map[i];802state->vertex_strides[i] = vb->buffer.resource ? vb->stride : 0;803hash = XXH32(&state->vertex_strides[i], sizeof(uint32_t), hash);804}805}806state->final_hash = XXH32(&state->element_state, sizeof(void*), hash);807state->vertex_state_dirty = false;808}809entry = _mesa_hash_table_search_pre_hashed(prog->pipelines[vkmode], state->final_hash, state);810811if (!entry) {812util_queue_fence_wait(&prog->base.cache_fence);813VkPipeline pipeline = zink_create_gfx_pipeline(screen, prog,814state, vkmode);815if (pipeline == VK_NULL_HANDLE)816return VK_NULL_HANDLE;817818struct gfx_pipeline_cache_entry *pc_entry = CALLOC_STRUCT(gfx_pipeline_cache_entry);819if (!pc_entry)820return VK_NULL_HANDLE;821822memcpy(&pc_entry->state, state, sizeof(*state));823pc_entry->pipeline = pipeline;824825entry = _mesa_hash_table_insert_pre_hashed(prog->pipelines[vkmode], state->final_hash, state, pc_entry);826assert(entry);827}828829struct gfx_pipeline_cache_entry *cache_entry = entry->data;830state->pipeline = cache_entry->pipeline;831state->mode = mode;832return state->pipeline;833}834835VkPipeline836zink_get_compute_pipeline(struct zink_screen *screen,837struct zink_compute_program *comp,838struct zink_compute_pipeline_state *state)839{840struct hash_entry *entry = NULL;841842if (!state->dirty)843return state->pipeline;844if (state->dirty) {845state->hash = hash_compute_pipeline_state(state);846state->dirty = false;847}848entry = _mesa_hash_table_search_pre_hashed(comp->pipelines, state->hash, state);849850if (!entry) {851util_queue_fence_wait(&comp->base.cache_fence);852VkPipeline pipeline = zink_create_compute_pipeline(screen, comp, state);853854if (pipeline == VK_NULL_HANDLE)855return VK_NULL_HANDLE;856857struct compute_pipeline_cache_entry *pc_entry = CALLOC_STRUCT(compute_pipeline_cache_entry);858if (!pc_entry)859return VK_NULL_HANDLE;860861memcpy(&pc_entry->state, state, sizeof(*state));862pc_entry->pipeline = pipeline;863864entry = _mesa_hash_table_insert_pre_hashed(comp->pipelines, state->hash, state, pc_entry);865assert(entry);866}867868struct compute_pipeline_cache_entry *cache_entry = entry->data;869state->pipeline = cache_entry->pipeline;870return state->pipeline;871}872873874static inline void875bind_stage(struct zink_context *ctx, enum pipe_shader_type stage,876struct zink_shader *shader)877{878if (stage == PIPE_SHADER_COMPUTE)879ctx->compute_stage = shader;880else881ctx->gfx_stages[stage] = shader;882ctx->dirty_shader_stages |= 1 << stage;883if (shader && shader->nir->info.num_inlinable_uniforms)884ctx->shader_has_inlinable_uniforms_mask |= 1 << stage;885else886ctx->shader_has_inlinable_uniforms_mask &= ~(1 << stage);887}888889static void890zink_bind_vs_state(struct pipe_context *pctx,891void *cso)892{893struct zink_context *ctx = zink_context(pctx);894bind_stage(ctx, PIPE_SHADER_VERTEX, cso);895if (!ctx->gfx_stages[PIPE_SHADER_GEOMETRY] &&896!ctx->gfx_stages[PIPE_SHADER_TESS_EVAL]) {897ctx->last_vertex_stage = cso;898}899}900901static void902zink_bind_fs_state(struct pipe_context *pctx,903void *cso)904{905bind_stage(zink_context(pctx), PIPE_SHADER_FRAGMENT, cso);906}907908static void909zink_bind_gs_state(struct pipe_context *pctx,910void *cso)911{912struct zink_context *ctx = zink_context(pctx);913if (!!ctx->gfx_stages[PIPE_SHADER_GEOMETRY] != !!cso)914ctx->dirty_shader_stages |= BITFIELD_BIT(PIPE_SHADER_VERTEX) |915BITFIELD_BIT(PIPE_SHADER_TESS_EVAL);916bind_stage(ctx, PIPE_SHADER_GEOMETRY, cso);917if (cso)918ctx->last_vertex_stage = cso;919else {920if (ctx->gfx_stages[PIPE_SHADER_TESS_EVAL])921ctx->last_vertex_stage = ctx->gfx_stages[PIPE_SHADER_TESS_EVAL];922else923ctx->last_vertex_stage = ctx->gfx_stages[PIPE_SHADER_VERTEX];924}925}926927static void928zink_bind_tcs_state(struct pipe_context *pctx,929void *cso)930{931bind_stage(zink_context(pctx), PIPE_SHADER_TESS_CTRL, cso);932}933934static void935zink_bind_tes_state(struct pipe_context *pctx,936void *cso)937{938struct zink_context *ctx = zink_context(pctx);939if (!!ctx->gfx_stages[PIPE_SHADER_TESS_EVAL] != !!cso) {940if (!cso) {941/* if unsetting a TESS that uses a generated TCS, ensure the TCS is unset */942if (ctx->gfx_stages[PIPE_SHADER_TESS_EVAL]->generated)943ctx->gfx_stages[PIPE_SHADER_TESS_CTRL] = NULL;944}945ctx->dirty_shader_stages |= BITFIELD_BIT(PIPE_SHADER_VERTEX);946}947bind_stage(ctx, PIPE_SHADER_TESS_EVAL, cso);948if (!ctx->gfx_stages[PIPE_SHADER_GEOMETRY]) {949if (cso)950ctx->last_vertex_stage = cso;951else952ctx->last_vertex_stage = ctx->gfx_stages[PIPE_SHADER_VERTEX];953}954}955956static void *957zink_create_cs_state(struct pipe_context *pctx,958const struct pipe_compute_state *shader)959{960struct nir_shader *nir;961if (shader->ir_type != PIPE_SHADER_IR_NIR)962nir = zink_tgsi_to_nir(pctx->screen, shader->prog);963else964nir = (struct nir_shader *)shader->prog;965966return zink_shader_create(zink_screen(pctx->screen), nir, NULL);967}968969static void970zink_bind_cs_state(struct pipe_context *pctx,971void *cso)972{973bind_stage(zink_context(pctx), PIPE_SHADER_COMPUTE, cso);974}975976void977zink_delete_shader_state(struct pipe_context *pctx, void *cso)978{979zink_shader_free(zink_context(pctx), cso);980}981982void *983zink_create_gfx_shader_state(struct pipe_context *pctx, const struct pipe_shader_state *shader)984{985nir_shader *nir;986if (shader->type != PIPE_SHADER_IR_NIR)987nir = zink_tgsi_to_nir(pctx->screen, shader->tokens);988else989nir = (struct nir_shader *)shader->ir.nir;990991return zink_shader_create(zink_screen(pctx->screen), nir, &shader->stream_output);992}993994static void995zink_delete_cached_shader_state(struct pipe_context *pctx, void *cso)996{997struct zink_screen *screen = zink_screen(pctx->screen);998util_shader_reference(pctx, &screen->shaders, &cso, NULL);999}10001001static void *1002zink_create_cached_shader_state(struct pipe_context *pctx, const struct pipe_shader_state *shader)1003{1004bool cache_hit;1005struct zink_screen *screen = zink_screen(pctx->screen);1006return util_live_shader_cache_get(pctx, &screen->shaders, shader, &cache_hit);1007}10081009void1010zink_program_init(struct zink_context *ctx)1011{1012ctx->base.create_vs_state = zink_create_cached_shader_state;1013ctx->base.bind_vs_state = zink_bind_vs_state;1014ctx->base.delete_vs_state = zink_delete_cached_shader_state;10151016ctx->base.create_fs_state = zink_create_cached_shader_state;1017ctx->base.bind_fs_state = zink_bind_fs_state;1018ctx->base.delete_fs_state = zink_delete_cached_shader_state;10191020ctx->base.create_gs_state = zink_create_cached_shader_state;1021ctx->base.bind_gs_state = zink_bind_gs_state;1022ctx->base.delete_gs_state = zink_delete_cached_shader_state;10231024ctx->base.create_tcs_state = zink_create_cached_shader_state;1025ctx->base.bind_tcs_state = zink_bind_tcs_state;1026ctx->base.delete_tcs_state = zink_delete_cached_shader_state;10271028ctx->base.create_tes_state = zink_create_cached_shader_state;1029ctx->base.bind_tes_state = zink_bind_tes_state;1030ctx->base.delete_tes_state = zink_delete_cached_shader_state;10311032ctx->base.create_compute_state = zink_create_cs_state;1033ctx->base.bind_compute_state = zink_bind_cs_state;1034ctx->base.delete_compute_state = zink_delete_shader_state;1035}103610371038