17ec681f3Smrg/*
27ec681f3Smrg * Copyright 2018 Collabora Ltd.
37ec681f3Smrg *
47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a
57ec681f3Smrg * copy of this software and associated documentation files (the "Software"),
67ec681f3Smrg * to deal in the Software without restriction, including without limitation
77ec681f3Smrg * on the rights to use, copy, modify, merge, publish, distribute, sub
87ec681f3Smrg * license, and/or sell copies of the Software, and to permit persons to whom
97ec681f3Smrg * the Software is furnished to do so, subject to the following conditions:
107ec681f3Smrg *
117ec681f3Smrg * The above copyright notice and this permission notice (including the next
127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the
137ec681f3Smrg * Software.
147ec681f3Smrg *
157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
187ec681f3Smrg * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
197ec681f3Smrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
207ec681f3Smrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
217ec681f3Smrg * USE OR OTHER DEALINGS IN THE SOFTWARE.
227ec681f3Smrg */
237ec681f3Smrg
247ec681f3Smrg#ifndef ZINK_PROGRAM_H
257ec681f3Smrg#define ZINK_PROGRAM_H
267ec681f3Smrg
277ec681f3Smrg#include <vulkan/vulkan.h>
287ec681f3Smrg
297ec681f3Smrg#include "compiler/shader_enums.h"
307ec681f3Smrg#include "pipe/p_state.h"
317ec681f3Smrg#include "util/u_inlines.h"
327ec681f3Smrg
337ec681f3Smrg#include "zink_context.h"
347ec681f3Smrg#include "zink_compiler.h"
357ec681f3Smrg#include "zink_shader_keys.h"
367ec681f3Smrg#ifdef __cplusplus
377ec681f3Smrgextern "C" {
387ec681f3Smrg#endif
397ec681f3Smrg
407ec681f3Smrgstruct zink_screen;
417ec681f3Smrgstruct zink_shader;
427ec681f3Smrgstruct zink_gfx_pipeline_state;
437ec681f3Smrgstruct zink_descriptor_set;
447ec681f3Smrg
457ec681f3Smrgstruct hash_table;
467ec681f3Smrgstruct set;
477ec681f3Smrgstruct util_dynarray;
487ec681f3Smrg
497ec681f3Smrgstruct zink_program;
507ec681f3Smrg
517ec681f3Smrgstruct zink_gfx_push_constant {
527ec681f3Smrg   unsigned draw_mode_is_indexed;
537ec681f3Smrg   unsigned draw_id;
547ec681f3Smrg   float default_inner_level[2];
557ec681f3Smrg   float default_outer_level[4];
567ec681f3Smrg};
577ec681f3Smrg
587ec681f3Smrgstruct zink_cs_push_constant {
597ec681f3Smrg   unsigned work_dim;
607ec681f3Smrg};
617ec681f3Smrg
627ec681f3Smrg/* a shader module is used for directly reusing a shader module between programs,
637ec681f3Smrg * e.g., in the case where we're swapping out only one shader,
647ec681f3Smrg * allowing us to skip going through shader keys
657ec681f3Smrg */
667ec681f3Smrgstruct zink_shader_module {
677ec681f3Smrg   struct list_head list;
687ec681f3Smrg   VkShaderModule shader;
697ec681f3Smrg   uint32_t hash;
707ec681f3Smrg   bool default_variant;
717ec681f3Smrg   uint8_t num_uniforms;
727ec681f3Smrg   uint8_t key_size;
737ec681f3Smrg   uint8_t key[0]; /* | key | uniforms | */
747ec681f3Smrg};
757ec681f3Smrg
767ec681f3Smrgstruct zink_program {
777ec681f3Smrg   struct pipe_reference reference;
787ec681f3Smrg   unsigned char sha1[20];
797ec681f3Smrg   struct util_queue_fence cache_fence;
807ec681f3Smrg   VkPipelineCache pipeline_cache;
817ec681f3Smrg   size_t pipeline_cache_size;
827ec681f3Smrg   struct zink_batch_usage *batch_uses;
837ec681f3Smrg   bool is_compute;
847ec681f3Smrg
857ec681f3Smrg   struct zink_program_descriptor_data *dd;
867ec681f3Smrg
877ec681f3Smrg   uint32_t compat_id;
887ec681f3Smrg   VkPipelineLayout layout;
897ec681f3Smrg   VkDescriptorSetLayout dsl[ZINK_DESCRIPTOR_TYPES + 2]; // one for each type + push + bindless
907ec681f3Smrg   unsigned num_dsl;
917ec681f3Smrg
927ec681f3Smrg   bool removed;
937ec681f3Smrg};
947ec681f3Smrg
957ec681f3Smrg#define ZINK_MAX_INLINED_VARIANTS 5
967ec681f3Smrg
977ec681f3Smrgstruct zink_gfx_program {
987ec681f3Smrg   struct zink_program base;
997ec681f3Smrg
1007ec681f3Smrg   uint32_t stages_present; //mask of stages present in this program
1017ec681f3Smrg   struct nir_shader *nir[ZINK_SHADER_COUNT];
1027ec681f3Smrg
1037ec681f3Smrg   struct zink_shader_module *modules[ZINK_SHADER_COUNT]; // compute stage doesn't belong here
1047ec681f3Smrg
1057ec681f3Smrg   struct zink_shader *last_vertex_stage;
1067ec681f3Smrg
1077ec681f3Smrg   struct list_head shader_cache[ZINK_SHADER_COUNT][2]; //normal, inline uniforms
1087ec681f3Smrg   unsigned inlined_variant_count[ZINK_SHADER_COUNT];
1097ec681f3Smrg
1107ec681f3Smrg   struct zink_shader *shaders[ZINK_SHADER_COUNT];
1117ec681f3Smrg   struct hash_table pipelines[11]; // number of draw modes we support
1127ec681f3Smrg   uint32_t default_variant_hash;
1137ec681f3Smrg   uint32_t last_variant_hash;
1147ec681f3Smrg};
1157ec681f3Smrg
1167ec681f3Smrgstruct zink_compute_program {
1177ec681f3Smrg   struct zink_program base;
1187ec681f3Smrg
1197ec681f3Smrg   struct zink_shader_module *module;
1207ec681f3Smrg   struct zink_shader *shader;
1217ec681f3Smrg   struct hash_table *pipelines;
1227ec681f3Smrg};
1237ec681f3Smrg
1247ec681f3Smrgstatic inline enum zink_descriptor_type
1257ec681f3Smrgzink_desc_type_from_vktype(VkDescriptorType type)
1267ec681f3Smrg{
1277ec681f3Smrg   switch (type) {
1287ec681f3Smrg   case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
1297ec681f3Smrg   case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
1307ec681f3Smrg      return ZINK_DESCRIPTOR_TYPE_UBO;
1317ec681f3Smrg   case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
1327ec681f3Smrg   case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
1337ec681f3Smrg      return ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW;
1347ec681f3Smrg   case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
1357ec681f3Smrg      return ZINK_DESCRIPTOR_TYPE_SSBO;
1367ec681f3Smrg   case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
1377ec681f3Smrg   case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
1387ec681f3Smrg      return ZINK_DESCRIPTOR_TYPE_IMAGE;
1397ec681f3Smrg   default:
1407ec681f3Smrg      unreachable("unhandled descriptor type");
1417ec681f3Smrg   }
1427ec681f3Smrg}
1437ec681f3Smrg
1447ec681f3Smrgstatic inline VkPrimitiveTopology
1457ec681f3Smrgzink_primitive_topology(enum pipe_prim_type mode)
1467ec681f3Smrg{
1477ec681f3Smrg   switch (mode) {
1487ec681f3Smrg   case PIPE_PRIM_POINTS:
1497ec681f3Smrg      return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
1507ec681f3Smrg
1517ec681f3Smrg   case PIPE_PRIM_LINES:
1527ec681f3Smrg      return VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
1537ec681f3Smrg
1547ec681f3Smrg   case PIPE_PRIM_LINE_STRIP:
1557ec681f3Smrg      return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
1567ec681f3Smrg
1577ec681f3Smrg   case PIPE_PRIM_TRIANGLES:
1587ec681f3Smrg      return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
1597ec681f3Smrg
1607ec681f3Smrg   case PIPE_PRIM_TRIANGLE_STRIP:
1617ec681f3Smrg      return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
1627ec681f3Smrg
1637ec681f3Smrg   case PIPE_PRIM_TRIANGLE_FAN:
1647ec681f3Smrg      return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN;
1657ec681f3Smrg
1667ec681f3Smrg   case PIPE_PRIM_LINE_STRIP_ADJACENCY:
1677ec681f3Smrg      return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY;
1687ec681f3Smrg
1697ec681f3Smrg   case PIPE_PRIM_LINES_ADJACENCY:
1707ec681f3Smrg      return VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY;
1717ec681f3Smrg
1727ec681f3Smrg   case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
1737ec681f3Smrg      return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY;
1747ec681f3Smrg
1757ec681f3Smrg   case PIPE_PRIM_TRIANGLES_ADJACENCY:
1767ec681f3Smrg      return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY;
1777ec681f3Smrg
1787ec681f3Smrg   case PIPE_PRIM_PATCHES:
1797ec681f3Smrg      return VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
1807ec681f3Smrg
1817ec681f3Smrg   default:
1827ec681f3Smrg      unreachable("unexpected enum pipe_prim_type");
1837ec681f3Smrg   }
1847ec681f3Smrg}
1857ec681f3Smrg
1867ec681f3Smrgvoid
1877ec681f3Smrgzink_delete_shader_state(struct pipe_context *pctx, void *cso);
1887ec681f3Smrgvoid *
1897ec681f3Smrgzink_create_gfx_shader_state(struct pipe_context *pctx, const struct pipe_shader_state *shader);
1907ec681f3Smrg
1917ec681f3Smrgunsigned
1927ec681f3Smrgzink_program_num_bindings_typed(const struct zink_program *pg, enum zink_descriptor_type type, bool is_compute);
1937ec681f3Smrg
1947ec681f3Smrgunsigned
1957ec681f3Smrgzink_program_num_bindings(const struct zink_program *pg, bool is_compute);
1967ec681f3Smrg
1977ec681f3Smrgbool
1987ec681f3Smrgzink_program_descriptor_is_buffer(struct zink_context *ctx, enum pipe_shader_type stage, enum zink_descriptor_type type, unsigned i);
1997ec681f3Smrg
2007ec681f3Smrgvoid
2017ec681f3Smrgzink_update_gfx_program(struct zink_context *ctx, struct zink_gfx_program *prog);
2027ec681f3Smrg
2037ec681f3Smrgstruct zink_gfx_program *
2047ec681f3Smrgzink_create_gfx_program(struct zink_context *ctx,
2057ec681f3Smrg                        struct zink_shader *stages[ZINK_SHADER_COUNT],
2067ec681f3Smrg                        unsigned vertices_per_patch);
2077ec681f3Smrg
2087ec681f3Smrgvoid
2097ec681f3Smrgzink_destroy_gfx_program(struct zink_screen *screen,
2107ec681f3Smrg                         struct zink_gfx_program *prog);
2117ec681f3Smrg
2127ec681f3SmrgVkPipeline
2137ec681f3Smrgzink_get_gfx_pipeline(struct zink_context *ctx,
2147ec681f3Smrg                      struct zink_gfx_program *prog,
2157ec681f3Smrg                      struct zink_gfx_pipeline_state *state,
2167ec681f3Smrg                      enum pipe_prim_type mode);
2177ec681f3Smrg
2187ec681f3Smrgvoid
2197ec681f3Smrgzink_program_init(struct zink_context *ctx);
2207ec681f3Smrg
2217ec681f3Smrguint32_t
2227ec681f3Smrgzink_program_get_descriptor_usage(struct zink_context *ctx, enum pipe_shader_type stage, enum zink_descriptor_type type);
2237ec681f3Smrg
2247ec681f3Smrgvoid
2257ec681f3Smrgdebug_describe_zink_gfx_program(char* buf, const struct zink_gfx_program *ptr);
2267ec681f3Smrg
2277ec681f3Smrgstatic inline bool
2287ec681f3Smrgzink_gfx_program_reference(struct zink_screen *screen,
2297ec681f3Smrg                           struct zink_gfx_program **dst,
2307ec681f3Smrg                           struct zink_gfx_program *src)
2317ec681f3Smrg{
2327ec681f3Smrg   struct zink_gfx_program *old_dst = dst ? *dst : NULL;
2337ec681f3Smrg   bool ret = false;
2347ec681f3Smrg
2357ec681f3Smrg   if (pipe_reference_described(old_dst ? &old_dst->base.reference : NULL, &src->base.reference,
2367ec681f3Smrg                                (debug_reference_descriptor)debug_describe_zink_gfx_program)) {
2377ec681f3Smrg      zink_destroy_gfx_program(screen, old_dst);
2387ec681f3Smrg      ret = true;
2397ec681f3Smrg   }
2407ec681f3Smrg   if (dst) *dst = src;
2417ec681f3Smrg   return ret;
2427ec681f3Smrg}
2437ec681f3Smrg
2447ec681f3Smrgstruct zink_compute_program *
2457ec681f3Smrgzink_create_compute_program(struct zink_context *ctx, struct zink_shader *shader);
2467ec681f3Smrgvoid
2477ec681f3Smrgzink_destroy_compute_program(struct zink_screen *screen,
2487ec681f3Smrg                         struct zink_compute_program *comp);
2497ec681f3Smrg
2507ec681f3Smrgvoid
2517ec681f3Smrgdebug_describe_zink_compute_program(char* buf, const struct zink_compute_program *ptr);
2527ec681f3Smrg
2537ec681f3Smrgstatic inline bool
2547ec681f3Smrgzink_compute_program_reference(struct zink_screen *screen,
2557ec681f3Smrg                           struct zink_compute_program **dst,
2567ec681f3Smrg                           struct zink_compute_program *src)
2577ec681f3Smrg{
2587ec681f3Smrg   struct zink_compute_program *old_dst = dst ? *dst : NULL;
2597ec681f3Smrg   bool ret = false;
2607ec681f3Smrg
2617ec681f3Smrg   if (pipe_reference_described(old_dst ? &old_dst->base.reference : NULL, &src->base.reference,
2627ec681f3Smrg                                (debug_reference_descriptor)debug_describe_zink_compute_program)) {
2637ec681f3Smrg      zink_destroy_compute_program(screen, old_dst);
2647ec681f3Smrg      ret = true;
2657ec681f3Smrg   }
2667ec681f3Smrg   if (dst) *dst = src;
2677ec681f3Smrg   return ret;
2687ec681f3Smrg}
2697ec681f3Smrg
2707ec681f3SmrgVkPipelineLayout
2717ec681f3Smrgzink_pipeline_layout_create(struct zink_screen *screen, struct zink_program *pg, uint32_t *compat);
2727ec681f3Smrg
2737ec681f3Smrgvoid
2747ec681f3Smrgzink_program_update_compute_pipeline_state(struct zink_context *ctx, struct zink_compute_program *comp, const uint block[3]);
2757ec681f3Smrg
2767ec681f3SmrgVkPipeline
2777ec681f3Smrgzink_get_compute_pipeline(struct zink_screen *screen,
2787ec681f3Smrg                      struct zink_compute_program *comp,
2797ec681f3Smrg                      struct zink_compute_pipeline_state *state);
2807ec681f3Smrg
2817ec681f3Smrgstatic inline bool
2827ec681f3Smrgzink_program_has_descriptors(const struct zink_program *pg)
2837ec681f3Smrg{
2847ec681f3Smrg   return pg->num_dsl > 0;
2857ec681f3Smrg}
2867ec681f3Smrg
2877ec681f3Smrgstatic inline struct zink_fs_key *
2887ec681f3Smrgzink_set_fs_key(struct zink_context *ctx)
2897ec681f3Smrg{
2907ec681f3Smrg   ctx->dirty_shader_stages |= BITFIELD_BIT(PIPE_SHADER_FRAGMENT);
2917ec681f3Smrg   return (struct zink_fs_key *)&ctx->gfx_pipeline_state.shader_keys.key[PIPE_SHADER_FRAGMENT];
2927ec681f3Smrg}
2937ec681f3Smrg
2947ec681f3Smrgstatic inline const struct zink_fs_key *
2957ec681f3Smrgzink_get_fs_key(struct zink_context *ctx)
2967ec681f3Smrg{
2977ec681f3Smrg   return (const struct zink_fs_key *)&ctx->gfx_pipeline_state.shader_keys.key[PIPE_SHADER_FRAGMENT];
2987ec681f3Smrg}
2997ec681f3Smrg
3007ec681f3Smrgvoid
3017ec681f3Smrgzink_update_fs_key_samples(struct zink_context *ctx);
3027ec681f3Smrg
3037ec681f3Smrgstatic inline struct zink_vs_key *
3047ec681f3Smrgzink_set_vs_key(struct zink_context *ctx)
3057ec681f3Smrg{
3067ec681f3Smrg   ctx->dirty_shader_stages |= BITFIELD_BIT(PIPE_SHADER_VERTEX);
3077ec681f3Smrg   return (struct zink_vs_key *)&ctx->gfx_pipeline_state.shader_keys.key[PIPE_SHADER_VERTEX];
3087ec681f3Smrg}
3097ec681f3Smrg
3107ec681f3Smrgstatic inline const struct zink_vs_key *
3117ec681f3Smrgzink_get_vs_key(struct zink_context *ctx)
3127ec681f3Smrg{
3137ec681f3Smrg   return (const struct zink_vs_key *)&ctx->gfx_pipeline_state.shader_keys.key[PIPE_SHADER_VERTEX];
3147ec681f3Smrg}
3157ec681f3Smrg
3167ec681f3Smrgstatic inline struct zink_vs_key_base *
3177ec681f3Smrgzink_set_last_vertex_key(struct zink_context *ctx)
3187ec681f3Smrg{
3197ec681f3Smrg   ctx->last_vertex_stage_dirty = true;
3207ec681f3Smrg   return (struct zink_vs_key_base *)&ctx->gfx_pipeline_state.shader_keys.last_vertex;
3217ec681f3Smrg}
3227ec681f3Smrg
3237ec681f3Smrgstatic inline const struct zink_vs_key_base *
3247ec681f3Smrgzink_get_last_vertex_key(struct zink_context *ctx)
3257ec681f3Smrg{
3267ec681f3Smrg   return (const struct zink_vs_key_base *)&ctx->gfx_pipeline_state.shader_keys.last_vertex;
3277ec681f3Smrg}
3287ec681f3Smrg
3297ec681f3Smrgstatic inline void
3307ec681f3Smrgzink_set_fs_point_coord_key(struct zink_context *ctx)
3317ec681f3Smrg{
3327ec681f3Smrg   const struct zink_fs_key *fs = zink_get_fs_key(ctx);
3337ec681f3Smrg   bool disable = !ctx->gfx_pipeline_state.has_points || !ctx->rast_state->base.sprite_coord_enable;
3347ec681f3Smrg   uint8_t coord_replace_bits = disable ? 0 : ctx->rast_state->base.sprite_coord_enable;
3357ec681f3Smrg   bool coord_replace_yinvert = disable ? false : !!ctx->rast_state->base.sprite_coord_mode;
3367ec681f3Smrg   if (fs->coord_replace_bits != coord_replace_bits || fs->coord_replace_yinvert != coord_replace_yinvert) {
3377ec681f3Smrg      zink_set_fs_key(ctx)->coord_replace_bits = coord_replace_bits;
3387ec681f3Smrg      zink_set_fs_key(ctx)->coord_replace_yinvert = coord_replace_yinvert;
3397ec681f3Smrg   }
3407ec681f3Smrg}
3417ec681f3Smrg
3427ec681f3Smrg#ifdef __cplusplus
3437ec681f3Smrg}
3447ec681f3Smrg#endif
3457ec681f3Smrg
3467ec681f3Smrg#endif
347