zink: use dynamic state3 rasterization states when available

this massively reduces the number of pipelines required

also temporarily disable GPL until a few more patches land since something's
weird and broken

Reviewed-by: Adam Jackson <ajax@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18890>
This commit is contained in:
Mike Blumenkrantz 2022-06-13 17:05:56 -04:00 committed by Marge Bot
parent 57f966ed1e
commit c7f46d2ad6
10 changed files with 163 additions and 186 deletions

View file

@ -191,6 +191,10 @@ EXTENSIONS = [
alias="dynamic_state2",
features=True,
conditions=["$feats.extendedDynamicState2"]),
Extension("VK_EXT_extended_dynamic_state3",
alias="dynamic_state3",
properties=True,
features=True),
Extension("VK_EXT_pipeline_creation_cache_control",
alias="pipeline_cache_control",
features=True,

View file

@ -125,18 +125,20 @@ zink_bind_vertex_buffers(struct zink_batch *batch, struct zink_context *ctx)
buffers[i] = res->obj->buffer;
buffer_offsets[i] = vb->buffer_offset;
buffer_strides[i] = vb->stride;
if (DYNAMIC_STATE == ZINK_DYNAMIC_VERTEX_INPUT)
if (DYNAMIC_STATE == ZINK_DYNAMIC_VERTEX_INPUT2 || DYNAMIC_STATE == ZINK_DYNAMIC_VERTEX_INPUT)
elems->hw_state.dynbindings[i].stride = vb->stride;
} else {
buffers[i] = zink_resource(ctx->dummy_vertex_buffer)->obj->buffer;
buffer_offsets[i] = 0;
buffer_strides[i] = 0;
if (DYNAMIC_STATE == ZINK_DYNAMIC_VERTEX_INPUT)
if (DYNAMIC_STATE == ZINK_DYNAMIC_VERTEX_INPUT2 || DYNAMIC_STATE == ZINK_DYNAMIC_VERTEX_INPUT)
elems->hw_state.dynbindings[i].stride = 0;
}
}
if (DYNAMIC_STATE != ZINK_NO_DYNAMIC_STATE && DYNAMIC_STATE != ZINK_DYNAMIC_VERTEX_INPUT) {
if (DYNAMIC_STATE != ZINK_NO_DYNAMIC_STATE &&
DYNAMIC_STATE != ZINK_DYNAMIC_VERTEX_INPUT2 &&
DYNAMIC_STATE != ZINK_DYNAMIC_VERTEX_INPUT) {
if (elems->hw_state.num_bindings)
VKCTX(CmdBindVertexBuffers2EXT)(batch->state->cmdbuf, 0,
elems->hw_state.num_bindings,
@ -146,7 +148,7 @@ zink_bind_vertex_buffers(struct zink_batch *batch, struct zink_context *ctx)
elems->hw_state.num_bindings,
buffers, buffer_offsets);
if (DYNAMIC_STATE == ZINK_DYNAMIC_VERTEX_INPUT)
if (DYNAMIC_STATE == ZINK_DYNAMIC_VERTEX_INPUT2 || DYNAMIC_STATE == ZINK_DYNAMIC_VERTEX_INPUT)
VKCTX(CmdSetVertexInputEXT)(batch->state->cmdbuf,
elems->hw_state.num_bindings, elems->hw_state.dynbindings,
elems->hw_state.num_attribs, elems->hw_state.dynattribs);
@ -631,10 +633,22 @@ zink_draw(struct pipe_context *pctx,
VKCTX(CmdSetCullModeEXT)(batch->state->cmdbuf, ctx->gfx_pipeline_state.dyn_state1.cull_mode);
}
if ((BATCH_CHANGED || rast_state_changed) &&
screen->info.have_EXT_line_rasterization && rast_state->base.line_stipple_enable)
(DYNAMIC_STATE >= ZINK_DYNAMIC_STATE3 || (screen->info.have_EXT_line_rasterization && rast_state->base.line_stipple_enable)))
VKCTX(CmdSetLineStippleEXT)(batch->state->cmdbuf, rast_state->base.line_stipple_factor, rast_state->base.line_stipple_pattern);
if (BATCH_CHANGED || ctx->rast_state_changed) {
if ((BATCH_CHANGED || rast_state_changed) && DYNAMIC_STATE >= ZINK_DYNAMIC_STATE3) {
VKCTX(CmdSetDepthClipEnableEXT)(batch->state->cmdbuf, rast_state->hw_state.depth_clip);
VKCTX(CmdSetDepthClampEnableEXT)(batch->state->cmdbuf, !rast_state->hw_state.depth_clip);
VKCTX(CmdSetPolygonModeEXT)(batch->state->cmdbuf, (VkPolygonMode)rast_state->hw_state.polygon_mode);
VKCTX(CmdSetDepthClipNegativeOneToOneEXT)(batch->state->cmdbuf, !rast_state->hw_state.clip_halfz);
VKCTX(CmdSetProvokingVertexModeEXT)(batch->state->cmdbuf, rast_state->hw_state.pv_last ?
VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT :
VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT);
VKCTX(CmdSetLineRasterizationModeEXT)(batch->state->cmdbuf, (VkLineRasterizationModeEXT)rast_state->hw_state.line_mode);
VKCTX(CmdSetLineStippleEnableEXT)(batch->state->cmdbuf, rast_state->hw_state.line_stipple_enable);
}
if (BATCH_CHANGED || rast_state_changed) {
enum pipe_prim_type reduced_prim = ctx->last_vertex_stage->reduced_prim;
if (reduced_prim == PIPE_PRIM_MAX)
reduced_prim = u_reduced_prim(mode);
@ -958,7 +972,7 @@ zink_launch_grid(struct pipe_context *pctx, const struct pipe_grid_info *info)
template <zink_multidraw HAS_MULTIDRAW, zink_dynamic_state DYNAMIC_STATE, bool BATCH_CHANGED>
static void
init_batch_changed_functions(struct zink_context *ctx, pipe_draw_vbo_func draw_vbo_array[2][4][2], pipe_draw_vertex_state_func draw_state_array[2][4][2])
init_batch_changed_functions(struct zink_context *ctx, pipe_draw_vbo_func draw_vbo_array[2][6][2], pipe_draw_vertex_state_func draw_state_array[2][6][2])
{
draw_vbo_array[HAS_MULTIDRAW][DYNAMIC_STATE][BATCH_CHANGED] = zink_draw_vbo<HAS_MULTIDRAW, DYNAMIC_STATE, BATCH_CHANGED>;
draw_state_array[HAS_MULTIDRAW][DYNAMIC_STATE][BATCH_CHANGED] = zink_draw_vertex_state<HAS_MULTIDRAW, DYNAMIC_STATE, BATCH_CHANGED>;
@ -966,7 +980,7 @@ init_batch_changed_functions(struct zink_context *ctx, pipe_draw_vbo_func draw_v
template <zink_multidraw HAS_MULTIDRAW, zink_dynamic_state DYNAMIC_STATE>
static void
init_dynamic_state_functions(struct zink_context *ctx, pipe_draw_vbo_func draw_vbo_array[2][4][2], pipe_draw_vertex_state_func draw_state_array[2][4][2])
init_dynamic_state_functions(struct zink_context *ctx, pipe_draw_vbo_func draw_vbo_array[2][6][2], pipe_draw_vertex_state_func draw_state_array[2][6][2])
{
init_batch_changed_functions<HAS_MULTIDRAW, DYNAMIC_STATE, false>(ctx, draw_vbo_array, draw_state_array);
init_batch_changed_functions<HAS_MULTIDRAW, DYNAMIC_STATE, true>(ctx, draw_vbo_array, draw_state_array);
@ -974,16 +988,18 @@ init_dynamic_state_functions(struct zink_context *ctx, pipe_draw_vbo_func draw_v
template <zink_multidraw HAS_MULTIDRAW>
static void
init_multidraw_functions(struct zink_context *ctx, pipe_draw_vbo_func draw_vbo_array[2][4][2], pipe_draw_vertex_state_func draw_state_array[2][4][2])
init_multidraw_functions(struct zink_context *ctx, pipe_draw_vbo_func draw_vbo_array[2][6][2], pipe_draw_vertex_state_func draw_state_array[2][6][2])
{
init_dynamic_state_functions<HAS_MULTIDRAW, ZINK_NO_DYNAMIC_STATE>(ctx, draw_vbo_array, draw_state_array);
init_dynamic_state_functions<HAS_MULTIDRAW, ZINK_DYNAMIC_STATE>(ctx, draw_vbo_array, draw_state_array);
init_dynamic_state_functions<HAS_MULTIDRAW, ZINK_DYNAMIC_STATE2>(ctx, draw_vbo_array, draw_state_array);
init_dynamic_state_functions<HAS_MULTIDRAW, ZINK_DYNAMIC_VERTEX_INPUT2>(ctx, draw_vbo_array, draw_state_array);
init_dynamic_state_functions<HAS_MULTIDRAW, ZINK_DYNAMIC_STATE3>(ctx, draw_vbo_array, draw_state_array);
init_dynamic_state_functions<HAS_MULTIDRAW, ZINK_DYNAMIC_VERTEX_INPUT>(ctx, draw_vbo_array, draw_state_array);
}
static void
init_all_draw_functions(struct zink_context *ctx, pipe_draw_vbo_func draw_vbo_array[2][4][2], pipe_draw_vertex_state_func draw_state_array[2][4][2])
init_all_draw_functions(struct zink_context *ctx, pipe_draw_vbo_func draw_vbo_array[2][6][2], pipe_draw_vertex_state_func draw_state_array[2][6][2])
{
init_multidraw_functions<ZINK_NO_MULTIDRAW>(ctx, draw_vbo_array, draw_state_array);
init_multidraw_functions<ZINK_MULTIDRAW>(ctx, draw_vbo_array, draw_state_array);
@ -1099,17 +1115,24 @@ extern "C"
void
zink_init_draw_functions(struct zink_context *ctx, struct zink_screen *screen)
{
pipe_draw_vbo_func draw_vbo_array[2][4] //multidraw, zink_dynamic_state
pipe_draw_vbo_func draw_vbo_array[2][6] //multidraw, zink_dynamic_state
[2]; //batch changed
pipe_draw_vertex_state_func draw_state_array[2][4] //multidraw, zink_dynamic_state
pipe_draw_vertex_state_func draw_state_array[2][6] //multidraw, zink_dynamic_state
[2]; //batch changed
zink_dynamic_state dynamic;
if (screen->info.have_EXT_extended_dynamic_state) {
if (screen->info.have_EXT_extended_dynamic_state2) {
if (screen->info.have_EXT_vertex_input_dynamic_state)
dynamic = ZINK_DYNAMIC_VERTEX_INPUT;
else
dynamic = ZINK_DYNAMIC_STATE2;
if (screen->info.have_EXT_extended_dynamic_state3) {
if (screen->info.have_EXT_vertex_input_dynamic_state)
dynamic = ZINK_DYNAMIC_VERTEX_INPUT;
else
dynamic = ZINK_DYNAMIC_STATE3;
} else {
if (screen->info.have_EXT_vertex_input_dynamic_state)
dynamic = ZINK_DYNAMIC_VERTEX_INPUT2;
else
dynamic = ZINK_DYNAMIC_STATE2;
}
} else {
dynamic = ZINK_DYNAMIC_STATE;
}

View file

@ -52,7 +52,7 @@ zink_create_gfx_pipeline(struct zink_screen *screen,
const uint8_t *binding_map,
VkPrimitiveTopology primitive_topology)
{
struct zink_rasterizer_hw_state *hw_rast_state = (void*)state;
struct zink_rasterizer_hw_state *hw_rast_state = (void*)&state->dyn_state3;
VkPipelineVertexInputStateCreateInfo vertex_input_state;
if (!screen->info.have_EXT_vertex_input_dynamic_state || !state->element_state->num_attribs || !state->uses_dynamic_stride) {
memset(&vertex_input_state, 0, sizeof(vertex_input_state));
@ -139,7 +139,7 @@ zink_create_gfx_pipeline(struct zink_screen *screen,
* data here as long as sample_mask is initialized on context creation
*/
ms_state.pSampleMask = &state->sample_mask;
if (hw_rast_state->force_persample_interp) {
if (state->force_persample_interp) {
ms_state.sampleShadingEnable = VK_TRUE;
ms_state.minSampleShading = 1.0;
} else if (state->min_samples > 0) {
@ -210,7 +210,7 @@ zink_create_gfx_pipeline(struct zink_screen *screen,
depth_stencil_state.back = state->dyn_state1.depth_stencil_alpha_state->stencil_back;
depth_stencil_state.depthWriteEnable = state->dyn_state1.depth_stencil_alpha_state->depth_write;
VkDynamicState dynamicStateEnables[30] = {
VkDynamicState dynamicStateEnables[64] = {
VK_DYNAMIC_STATE_LINE_WIDTH,
VK_DYNAMIC_STATE_DEPTH_BIAS,
VK_DYNAMIC_STATE_BLEND_CONSTANTS,
@ -248,6 +248,16 @@ zink_create_gfx_pipeline(struct zink_screen *screen,
if (screen->info.dynamic_state2_feats.extendedDynamicState2PatchControlPoints)
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT;
}
if (screen->info.have_EXT_extended_dynamic_state3) {
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT;
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_DEPTH_CLIP_ENABLE_EXT;
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_POLYGON_MODE_EXT;
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_PROVOKING_VERTEX_MODE_EXT;
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_DEPTH_CLIP_NEGATIVE_ONE_TO_ONE_EXT;
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_LINE_RASTERIZATION_MODE_EXT;
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT;
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_LINE_STIPPLE_EXT;
}
if (screen->info.have_EXT_color_write_enable)
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT;
@ -603,8 +613,7 @@ zink_create_gfx_pipeline_input(struct zink_screen *screen,
}
VkPipeline
zink_create_gfx_pipeline_library(struct zink_screen *screen, struct zink_gfx_program *prog,
struct zink_rasterizer_hw_state *hw_rast_state, bool line)
zink_create_gfx_pipeline_library(struct zink_screen *screen, struct zink_gfx_program *prog)
{
assert(screen->info.have_EXT_extended_dynamic_state && screen->info.have_EXT_extended_dynamic_state2);
VkPipelineRenderingCreateInfo rendering_info;
@ -618,56 +627,21 @@ zink_create_gfx_pipeline_library(struct zink_screen *screen, struct zink_gfx_pro
};
VkPipelineViewportStateCreateInfo viewport_state = {0};
VkPipelineViewportDepthClipControlCreateInfoEXT clip = {
VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_DEPTH_CLIP_CONTROL_CREATE_INFO_EXT,
NULL,
VK_TRUE
};
viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewport_state.viewportCount = 0;
viewport_state.pViewports = NULL;
viewport_state.scissorCount = 0;
viewport_state.pScissors = NULL;
if (!screen->driver_workarounds.depth_clip_control_missing && !hw_rast_state->clip_halfz)
viewport_state.pNext = &clip;
VkPipelineRasterizationStateCreateInfo rast_state = {0};
rast_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rast_state.depthClampEnable = VK_TRUE;
rast_state.polygonMode = hw_rast_state->polygon_mode;
rast_state.depthBiasEnable = VK_TRUE;
rast_state.depthBiasConstantFactor = 0.0;
rast_state.depthBiasClamp = 0.0;
rast_state.depthBiasSlopeFactor = 0.0;
VkPipelineRasterizationDepthClipStateCreateInfoEXT depth_clip_state = {0};
depth_clip_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT;
depth_clip_state.depthClipEnable = hw_rast_state->depth_clip;
if (screen->info.have_EXT_depth_clip_enable) {
depth_clip_state.pNext = rast_state.pNext;
rast_state.pNext = &depth_clip_state;
} else {
static bool warned = false;
warn_missing_feature(warned, "VK_EXT_depth_clip_enable");
rast_state.depthClampEnable = !hw_rast_state->depth_clip;
}
VkPipelineRasterizationProvokingVertexStateCreateInfoEXT pv_state;
pv_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT;
pv_state.provokingVertexMode = hw_rast_state->pv_last ?
VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT :
VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT;
if (screen->info.have_EXT_provoking_vertex && hw_rast_state->pv_last) {
pv_state.pNext = rast_state.pNext;
rast_state.pNext = &pv_state;
}
rast_state.depthClampEnable = VK_TRUE;
VkPipelineDepthStencilStateCreateInfo depth_stencil_state = {0};
depth_stencil_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
VkDynamicState dynamicStateEnables[30] = {
VkDynamicState dynamicStateEnables[64] = {
VK_DYNAMIC_STATE_LINE_WIDTH,
VK_DYNAMIC_STATE_DEPTH_BIAS,
VK_DYNAMIC_STATE_STENCIL_REFERENCE,
@ -690,61 +664,14 @@ zink_create_gfx_pipeline_library(struct zink_screen *screen, struct zink_gfx_pro
if (screen->info.dynamic_state2_feats.extendedDynamicState2PatchControlPoints)
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT;
VkPipelineRasterizationLineStateCreateInfoEXT rast_line_state;
if (screen->info.have_EXT_line_rasterization) {
rast_line_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT;
rast_line_state.pNext = rast_state.pNext;
rast_line_state.stippledLineEnable = VK_FALSE;
rast_line_state.lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT;
bool check_warn = line;
if (prog->nir[MESA_SHADER_TESS_EVAL]) {
check_warn |= !prog->nir[MESA_SHADER_TESS_EVAL]->info.tess.point_mode &&
prog->nir[MESA_SHADER_TESS_EVAL]->info.tess._primitive_mode == TESS_PRIMITIVE_ISOLINES;
}
if (prog->nir[MESA_SHADER_GEOMETRY]) {
switch (prog->nir[MESA_SHADER_GEOMETRY]->info.gs.output_primitive) {
case SHADER_PRIM_LINES:
case SHADER_PRIM_LINE_LOOP:
case SHADER_PRIM_LINE_STRIP:
case SHADER_PRIM_LINES_ADJACENCY:
case SHADER_PRIM_LINE_STRIP_ADJACENCY:
check_warn = true;
break;
default: break;
}
}
if (check_warn) {
const char *features[4][2] = {
[VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT] = {"",""},
[VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT] = {"rectangularLines", "stippledRectangularLines"},
[VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT] = {"bresenhamLines", "stippledBresenhamLines"},
[VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT] = {"smoothLines", "stippledSmoothLines"},
};
static bool warned[6] = {0};
const VkPhysicalDeviceLineRasterizationFeaturesEXT *line_feats = &screen->info.line_rast_feats;
/* line features can be represented as an array VkBool32[6],
* with the 3 base features preceding the 3 (matching) stippled features
*/
const VkBool32 *feat = &line_feats->rectangularLines;
unsigned mode_idx = hw_rast_state->line_mode - VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT;
/* add base mode index, add 3 if stippling is enabled */
mode_idx += hw_rast_state->line_stipple_enable * 3;
if (*(feat + mode_idx))
rast_line_state.lineRasterizationMode = hw_rast_state->line_mode;
else
warn_missing_feature(warned[mode_idx], features[hw_rast_state->line_mode][hw_rast_state->line_stipple_enable]);
}
if (hw_rast_state->line_stipple_enable) {
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_LINE_STIPPLE_EXT;
rast_line_state.stippledLineEnable = VK_TRUE;
}
rast_state.pNext = &rast_line_state;
}
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT;
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_DEPTH_CLIP_ENABLE_EXT;
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_POLYGON_MODE_EXT;
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_PROVOKING_VERTEX_MODE_EXT;
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_DEPTH_CLIP_NEGATIVE_ONE_TO_ONE_EXT;
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_LINE_RASTERIZATION_MODE_EXT;
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT;
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_LINE_STIPPLE_EXT;
assert(state_count < ARRAY_SIZE(dynamicStateEnables));
VkPipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo = {0};
@ -771,7 +698,7 @@ zink_create_gfx_pipeline_library(struct zink_screen *screen, struct zink_gfx_pro
static bool warned = false;
warn_missing_feature(warned, "extendedDynamicState2PatchControlPoints");
}
tci.patchControlPoints = prog->shaders[MESA_SHADER_TESS_EVAL]->nir->info.tess._primitive_mode == TESS_PRIMITIVE_ISOLINES ? 2 : 3;
tci.patchControlPoints = 32;
pci.pTessellationState = &tci;
tci.pNext = &tdci;
tdci.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO;

View file

@ -48,8 +48,7 @@ zink_create_gfx_pipeline_input(struct zink_screen *screen,
const uint8_t *binding_map,
VkPrimitiveTopology primitive_topology);
VkPipeline
zink_create_gfx_pipeline_library(struct zink_screen *screen, struct zink_gfx_program *prog,
struct zink_rasterizer_hw_state *hw_rast_state, bool line);
zink_create_gfx_pipeline_library(struct zink_screen *screen, struct zink_gfx_program *prog);
VkPipeline
zink_create_gfx_pipeline_output(struct zink_screen *screen, struct zink_gfx_pipeline_state *state);
VkPipeline

View file

@ -453,7 +453,7 @@ generate_gfx_program_modules_optimal(struct zink_context *ctx, struct zink_scree
static uint32_t
hash_pipeline_lib(const void *key)
{
return _mesa_hash_data(key, sizeof(struct zink_rasterizer_hw_state));
return 1;
}
static bool
@ -465,7 +465,7 @@ equals_pipeline_lib(const void *a, const void *b)
static bool
equals_pipeline_lib_optimal(const void *a, const void *b)
{
return !memcmp(a, b, sizeof(uint32_t) * 2);
return !memcmp(a, b, sizeof(uint32_t));
}
uint32_t
@ -507,10 +507,7 @@ uint32_t
hash_gfx_output(const void *key)
{
const uint8_t *data = key;
const struct zink_gfx_output_key *okey = key;
/* manually add in force_persample_interp */
return okey->force_persample_interp ^
_mesa_hash_data(data + sizeof(uint16_t), offsetof(struct zink_gfx_output_key, pipeline) - sizeof(uint16_t));
return _mesa_hash_data(data, offsetof(struct zink_gfx_output_key, pipeline));
}
static bool
@ -518,7 +515,7 @@ equals_gfx_output(const void *a, const void *b)
{
const uint8_t *da = a;
const uint8_t *db = b;
return !memcmp(da + sizeof(uint16_t), db + sizeof(uint16_t), offsetof(struct zink_gfx_output_key, pipeline) - sizeof(uint16_t));
return !memcmp(da, db, offsetof(struct zink_gfx_output_key, pipeline));
}
ALWAYS_INLINE static void
@ -882,12 +879,7 @@ zink_create_gfx_program(struct zink_context *ctx,
}
}
for (unsigned i = 0; i < ARRAY_SIZE(prog->libs); i++) {
if (screen->optimal_keys)
_mesa_set_init(&prog->libs[i], prog, hash_pipeline_lib, equals_pipeline_lib_optimal);
else
_mesa_set_init(&prog->libs[i], prog, hash_pipeline_lib, equals_pipeline_lib);
}
_mesa_set_init(&prog->libs, prog, hash_pipeline_lib, screen->optimal_keys ? equals_pipeline_lib_optimal : equals_pipeline_lib);
struct mesa_sha1 sctx;
_mesa_sha1_init(&sctx);
@ -1145,11 +1137,9 @@ zink_destroy_gfx_program(struct zink_screen *screen,
ralloc_free(prog->nir[i]);
}
for (unsigned i = 0; i < ARRAY_SIZE(prog->libs); i++) {
set_foreach_remove(&prog->libs[i], he) {
struct zink_gfx_library_key *gkey = (void*)he->key;
VKSCR(DestroyPipeline)(screen->dev, gkey->pipeline, NULL);
}
set_foreach_remove(&prog->libs, he) {
struct zink_gfx_library_key *gkey = (void*)he->key;
VKSCR(DestroyPipeline)(screen->dev, gkey->pipeline, NULL);
}
unsigned max_idx = ARRAY_SIZE(prog->pipelines[0]);
@ -1526,14 +1516,12 @@ zink_create_cached_shader_state(struct pipe_context *pctx, const struct pipe_sha
}
void
zink_create_pipeline_lib(struct zink_screen *screen, struct zink_gfx_program *prog, struct zink_gfx_pipeline_state *state, enum pipe_prim_type mode)
zink_create_pipeline_lib(struct zink_screen *screen, struct zink_gfx_program *prog, struct zink_gfx_pipeline_state *state)
{
struct zink_gfx_library_key *gkey = rzalloc(prog, struct zink_gfx_library_key);
gkey->hw_rast_state = state->rast_state;
memcpy(gkey->modules, state->modules, sizeof(gkey->modules));
bool line = u_reduced_prim(mode) == PIPE_PRIM_LINES;
gkey->pipeline = zink_create_gfx_pipeline_library(screen, prog, (struct zink_rasterizer_hw_state*)state, line);
_mesa_set_add(&prog->libs[get_primtype_idx(mode)], gkey);
gkey->pipeline = zink_create_gfx_pipeline_library(screen, prog);
_mesa_set_add(&prog->libs, gkey);
}
void
@ -1576,9 +1564,6 @@ zink_program_init(struct zink_context *ctx)
STATIC_ASSERT(offsetof(struct zink_gfx_pipeline_state, element_state) - offsetof(struct zink_gfx_pipeline_state, input) ==
offsetof(struct zink_gfx_input_key, element_state) - offsetof(struct zink_gfx_input_key, input));
STATIC_ASSERT(offsetof(struct zink_gfx_pipeline_state, modules) - offsetof(struct zink_gfx_pipeline_state, gkey) ==
offsetof(struct zink_gfx_library_key, modules) - offsetof(struct zink_gfx_library_key, hw_rast_state));
STATIC_ASSERT(sizeof(union zink_shader_key_optimal) == sizeof(uint32_t));
}

View file

@ -125,7 +125,7 @@ zink_gfx_program_update_optimal(struct zink_context *ctx);
void
zink_create_pipeline_lib(struct zink_screen *screen, struct zink_gfx_program *prog, struct zink_gfx_pipeline_state *state, enum pipe_prim_type mode);
zink_create_pipeline_lib(struct zink_screen *screen, struct zink_gfx_program *prog, struct zink_gfx_pipeline_state *state);
uint32_t hash_gfx_output(const void *key);
uint32_t hash_gfx_input(const void *key);
uint32_t hash_gfx_input_dynamic(const void *key);

View file

@ -37,6 +37,8 @@ hash_gfx_pipeline_state(const void *key)
const struct zink_gfx_pipeline_state *state = (const struct zink_gfx_pipeline_state *)key;
uint32_t hash = _mesa_hash_data(key, offsetof(struct zink_gfx_pipeline_state, hash));
if (DYNAMIC_STATE < ZINK_DYNAMIC_STATE2)
hash = XXH32(&state->dyn_state3, sizeof(state->dyn_state3), hash);
if (DYNAMIC_STATE < ZINK_DYNAMIC_STATE3)
hash = XXH32(&state->dyn_state2, sizeof(state->dyn_state2), hash);
if (DYNAMIC_STATE != ZINK_NO_DYNAMIC_STATE)
return hash;
@ -99,7 +101,6 @@ find_or_create_output(struct zink_context *ctx)
if (!he) {
struct zink_gfx_output_key *okey = rzalloc(ctx, struct zink_gfx_output_key);
memcpy(okey, &ctx->gfx_pipeline_state, offsetof(struct zink_gfx_output_key, pipeline));
okey->_pad = 0;
okey->pipeline = zink_create_gfx_pipeline_output(zink_screen(ctx->base.screen), &ctx->gfx_pipeline_state);
he = _mesa_set_add_pre_hashed(&ctx->gfx_outputs, hash, okey);
}
@ -140,10 +141,12 @@ zink_get_gfx_pipeline(struct zink_context *ctx,
bool uses_dynamic_stride = state->uses_dynamic_stride;
VkPrimitiveTopology vkmode = zink_primitive_topology(mode);
const unsigned idx = get_pipeline_idx<DYNAMIC_STATE >= ZINK_DYNAMIC_STATE>(mode, vkmode);
const unsigned idx = screen->info.dynamic_state3_props.dynamicPrimitiveTopologyUnrestricted ?
0 :
get_pipeline_idx<DYNAMIC_STATE >= ZINK_DYNAMIC_STATE>(mode, vkmode);
assert(idx <= ARRAY_SIZE(prog->pipelines[0]));
if (!state->dirty && !state->modules_changed &&
(DYNAMIC_STATE == ZINK_DYNAMIC_VERTEX_INPUT || !ctx->vertex_state_changed) &&
((DYNAMIC_STATE == ZINK_DYNAMIC_VERTEX_INPUT || DYNAMIC_STATE == ZINK_DYNAMIC_VERTEX_INPUT2) && !ctx->vertex_state_changed) &&
idx == state->idx)
return state->pipeline;
@ -161,7 +164,7 @@ zink_get_gfx_pipeline(struct zink_context *ctx,
assert(opt->val == state->shader_keys_optimal.key.val);
assert(state->optimal_key == state->shader_keys_optimal.key.val);
}
if (DYNAMIC_STATE < ZINK_DYNAMIC_VERTEX_INPUT && ctx->vertex_state_changed) {
if (DYNAMIC_STATE != ZINK_DYNAMIC_VERTEX_INPUT2 && DYNAMIC_STATE != ZINK_DYNAMIC_VERTEX_INPUT && ctx->vertex_state_changed) {
if (state->pipeline)
state->final_hash ^= state->vertex_hash;
if (DYNAMIC_STATE != ZINK_NO_DYNAMIC_STATE)
@ -189,7 +192,7 @@ zink_get_gfx_pipeline(struct zink_context *ctx,
ctx->vertex_state_changed = false;
const int rp_idx = state->render_pass ? 1 : 0;
if (DYNAMIC_STATE >= ZINK_DYNAMIC_VERTEX_INPUT) {
if (DYNAMIC_STATE == ZINK_DYNAMIC_VERTEX_INPUT || DYNAMIC_STATE == ZINK_DYNAMIC_VERTEX_INPUT2) {
if (prog->last_finalized_hash[rp_idx][idx] == state->final_hash && !prog->inline_variants && likely(prog->last_pipeline[rp_idx][idx])) {
state->pipeline = prog->last_pipeline[rp_idx][idx];
return state->pipeline;
@ -208,18 +211,15 @@ zink_get_gfx_pipeline(struct zink_context *ctx,
!zink_get_fs_key(ctx)->fbfetch_ms &&
!ctx->gfx_pipeline_state.force_persample_interp &&
!ctx->gfx_pipeline_state.min_samples) {
ctx->gfx_pipeline_state.gkey = ctx->gfx_pipeline_state.rast_state;
struct set_entry *he = NULL;
/* TODO: this will eventually be pre-populated by async shader compile */
//struct set_entry *he = _mesa_set_search(&prog->libs[idx], &ctx->gfx_pipeline_state.gkey);
struct set_entry *he = _mesa_set_search(&prog->libs, ctx->gfx_pipeline_state.modules);
if (!he && (zink_debug & ZINK_DEBUG_GPL)) {
zink_create_pipeline_lib(screen, prog, &ctx->gfx_pipeline_state, mode);
he = _mesa_set_search(&prog->libs[idx], &ctx->gfx_pipeline_state.gkey);
zink_create_pipeline_lib(screen, prog, &ctx->gfx_pipeline_state);
he = _mesa_set_search(&prog->libs, ctx->gfx_pipeline_state.modules);
assert(he);
}
if (he) {
struct zink_gfx_library_key *gkey = (struct zink_gfx_library_key *)he->key;
struct zink_gfx_input_key *ikey = DYNAMIC_STATE == ZINK_DYNAMIC_VERTEX_INPUT ?
struct zink_gfx_input_key *ikey = DYNAMIC_STATE == ZINK_DYNAMIC_VERTEX_INPUT || DYNAMIC_STATE == ZINK_DYNAMIC_VERTEX_INPUT2 ?
find_or_create_input_dynamic(ctx, vkmode) :
find_or_create_input(ctx, vkmode);
struct zink_gfx_output_key *okey = find_or_create_output(ctx);
@ -288,10 +288,16 @@ equals_gfx_pipeline_state(const void *a, const void *b)
sizeof(struct zink_depth_stencil_alpha_hw_state))))
return false;
}
if (DYNAMIC_STATE < ZINK_PIPELINE_DYNAMIC_STATE2) {
if (memcmp(&sa->dyn_state2, &sb->dyn_state2, sizeof(sa->dyn_state2)))
if (DYNAMIC_STATE < ZINK_PIPELINE_DYNAMIC_STATE3) {
if (DYNAMIC_STATE < ZINK_PIPELINE_DYNAMIC_STATE2) {
if (memcmp(&sa->dyn_state2, &sb->dyn_state2, sizeof(sa->dyn_state2)))
return false;
}
if (memcmp(&sa->dyn_state3, &sb->dyn_state3, sizeof(sa->dyn_state3)))
return false;
} else if (DYNAMIC_STATE != ZINK_PIPELINE_DYNAMIC_STATE2_PCP &&
DYNAMIC_STATE != ZINK_PIPELINE_DYNAMIC_VERTEX_INPUT2_PCP &&
DYNAMIC_STATE != ZINK_PIPELINE_DYNAMIC_STATE3_PCP &&
DYNAMIC_STATE != ZINK_PIPELINE_DYNAMIC_VERTEX_INPUT_PCP &&
(STAGE_MASK & BITFIELD_BIT(MESA_SHADER_TESS_EVAL)) &&
!(STAGE_MASK & BITFIELD_BIT(MESA_SHADER_TESS_CTRL))) {
@ -375,11 +381,24 @@ zink_get_gfx_pipeline_eq_func(struct zink_screen *screen, struct zink_gfx_progra
{
if (screen->info.have_EXT_extended_dynamic_state) {
if (screen->info.have_EXT_extended_dynamic_state2) {
if (screen->info.have_EXT_extended_dynamic_state3) {
if (screen->info.have_EXT_vertex_input_dynamic_state) {
if (screen->info.dynamic_state2_feats.extendedDynamicState2PatchControlPoints)
return get_gfx_pipeline_stage_eq_func<ZINK_PIPELINE_DYNAMIC_VERTEX_INPUT_PCP>(prog, screen->optimal_keys);
else
return get_gfx_pipeline_stage_eq_func<ZINK_PIPELINE_DYNAMIC_VERTEX_INPUT>(prog, screen->optimal_keys);
} else {
if (screen->info.dynamic_state2_feats.extendedDynamicState2PatchControlPoints)
return get_gfx_pipeline_stage_eq_func<ZINK_PIPELINE_DYNAMIC_STATE3_PCP>(prog, screen->optimal_keys);
else
return get_gfx_pipeline_stage_eq_func<ZINK_PIPELINE_DYNAMIC_STATE3>(prog, screen->optimal_keys);
}
}
if (screen->info.have_EXT_vertex_input_dynamic_state) {
if (screen->info.dynamic_state2_feats.extendedDynamicState2PatchControlPoints)
return get_gfx_pipeline_stage_eq_func<ZINK_PIPELINE_DYNAMIC_VERTEX_INPUT_PCP>(prog, screen->optimal_keys);
return get_gfx_pipeline_stage_eq_func<ZINK_PIPELINE_DYNAMIC_VERTEX_INPUT2_PCP>(prog, screen->optimal_keys);
else
return get_gfx_pipeline_stage_eq_func<ZINK_PIPELINE_DYNAMIC_VERTEX_INPUT>(prog, screen->optimal_keys);
return get_gfx_pipeline_stage_eq_func<ZINK_PIPELINE_DYNAMIC_VERTEX_INPUT2>(prog, screen->optimal_keys);
} else {
if (screen->info.dynamic_state2_feats.extendedDynamicState2PatchControlPoints)
return get_gfx_pipeline_stage_eq_func<ZINK_PIPELINE_DYNAMIC_STATE2_PCP>(prog, screen->optimal_keys);

View file

@ -2239,18 +2239,28 @@ init_driver_workarounds(struct zink_screen *screen)
default:
break;
}
if (screen->info.line_rast_feats.stippledRectangularLines &&
screen->info.line_rast_feats.stippledBresenhamLines &&
screen->info.line_rast_feats.stippledSmoothLines &&
!screen->info.dynamic_state3_feats.extendedDynamicState3LineStippleEnable)
screen->info.have_EXT_extended_dynamic_state3 = false;
if (!screen->info.dynamic_state3_feats.extendedDynamicState3PolygonMode ||
!screen->info.dynamic_state3_feats.extendedDynamicState3DepthClampEnable ||
!screen->info.dynamic_state3_feats.extendedDynamicState3DepthClipEnable ||
!screen->info.dynamic_state3_feats.extendedDynamicState3ProvokingVertexMode ||
!screen->info.dynamic_state3_feats.extendedDynamicState3LineRasterizationMode)
screen->info.have_EXT_extended_dynamic_state3 = false;
if (screen->info.have_EXT_graphics_pipeline_library)
screen->info.have_EXT_graphics_pipeline_library = screen->info.have_EXT_extended_dynamic_state &&
screen->info.have_EXT_extended_dynamic_state2 &&
((zink_debug & ZINK_DEBUG_GPL) ||
screen->info.dynamic_state2_feats.extendedDynamicState2PatchControlPoints) &&
screen->info.have_EXT_extended_dynamic_state3 &&
screen->info.have_KHR_dynamic_rendering &&
screen->info.have_EXT_non_seamless_cube_map &&
(screen->info.gpl_props.graphicsPipelineLibraryFastLinking ||
screen->is_cpu ||
(zink_debug & ZINK_DEBUG_GPL));
if (!(zink_debug & ZINK_DEBUG_GPL))
screen->info.have_EXT_graphics_pipeline_library = false;
(!(zink_debug & ZINK_DEBUG_GPL) ||
screen->info.gpl_props.graphicsPipelineLibraryFastLinking ||
screen->is_cpu);
screen->driver_workarounds.broken_l4a4 = screen->info.driver_props.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY;
screen->driver_workarounds.depth_clip_control_missing = !screen->info.have_EXT_depth_clip_control;
if (screen->info.driver_props.driverID == VK_DRIVER_ID_AMD_PROPRIETARY)
@ -2570,6 +2580,8 @@ zink_internal_create_screen(const struct pipe_screen_config *config)
mesa_loge("zink: failed to create copy context");
goto fail;
}
/* temporarily disabled */
screen->info.have_EXT_graphics_pipeline_library = false;
if (!(zink_debug & ZINK_DEBUG_GPL))
screen->optimal_keys = !screen->need_decompose_attrs && screen->info.have_EXT_non_seamless_cube_map && !screen->driconf.inline_uniforms;

View file

@ -582,7 +582,6 @@ zink_create_rasterizer_state(struct pipe_context *pctx,
assert(rs_state->depth_clip_far == rs_state->depth_clip_near);
state->hw_state.depth_clip = rs_state->depth_clip_near;
state->hw_state.force_persample_interp = rs_state->force_persample_interp;
state->hw_state.pv_last = !rs_state->flatshade_first;
state->hw_state.clip_halfz = rs_state->clip_halfz;
@ -635,7 +634,7 @@ zink_bind_rasterizer_state(struct pipe_context *pctx, void *cso)
bool point_quad_rasterization = ctx->rast_state ? ctx->rast_state->base.point_quad_rasterization : false;
bool scissor = ctx->rast_state ? ctx->rast_state->base.scissor : false;
bool pv_last = ctx->rast_state ? ctx->rast_state->hw_state.pv_last : false;
bool force_persample_interp = ctx->rast_state ? ctx->rast_state->hw_state.force_persample_interp : false;
bool force_persample_interp = ctx->gfx_pipeline_state.force_persample_interp;
bool clip_halfz = ctx->rast_state ? ctx->rast_state->hw_state.clip_halfz : false;
bool rasterizer_discard = ctx->rast_state ? ctx->rast_state->base.rasterizer_discard : false;
bool half_pixel_center = ctx->rast_state ? ctx->rast_state->base.half_pixel_center : true;
@ -647,11 +646,9 @@ zink_bind_rasterizer_state(struct pipe_context *pctx, void *cso)
/* without this prop, change in pv mode requires new rp */
!screen->info.pv_props.provokingVertexModePerPipeline)
zink_batch_no_rp(ctx);
uint32_t rast_bits = 0;
memcpy(&rast_bits, &ctx->rast_state->hw_state, sizeof(struct zink_rasterizer_hw_state));
ctx->gfx_pipeline_state.rast_state = rast_bits & BITFIELD_MASK(ZINK_RAST_HW_STATE_SIZE);
memcpy(&ctx->gfx_pipeline_state.dyn_state3, &ctx->rast_state->hw_state, sizeof(struct zink_rasterizer_hw_state));
ctx->gfx_pipeline_state.dirty = true;
ctx->gfx_pipeline_state.dirty |= !zink_screen(pctx->screen)->info.have_EXT_extended_dynamic_state3;
ctx->rast_state_changed = true;
if (clip_halfz != ctx->rast_state->base.clip_halfz) {
@ -680,8 +677,10 @@ zink_bind_rasterizer_state(struct pipe_context *pctx, void *cso)
if (ctx->rast_state->base.scissor != scissor)
ctx->scissor_changed = true;
if (ctx->rast_state->base.force_persample_interp != force_persample_interp)
if (ctx->rast_state->base.force_persample_interp != force_persample_interp) {
zink_set_fs_key(ctx)->force_persample_interp = ctx->rast_state->base.force_persample_interp;
ctx->gfx_pipeline_state.dirty = true;
}
ctx->gfx_pipeline_state.force_persample_interp = ctx->rast_state->base.force_persample_interp;
if (ctx->rast_state->base.half_pixel_center != half_pixel_center)

View file

@ -97,6 +97,8 @@ typedef enum {
ZINK_NO_DYNAMIC_STATE,
ZINK_DYNAMIC_STATE,
ZINK_DYNAMIC_STATE2,
ZINK_DYNAMIC_VERTEX_INPUT2,
ZINK_DYNAMIC_STATE3,
ZINK_DYNAMIC_VERTEX_INPUT,
} zink_dynamic_state;
@ -105,6 +107,10 @@ typedef enum {
ZINK_PIPELINE_DYNAMIC_STATE,
ZINK_PIPELINE_DYNAMIC_STATE2,
ZINK_PIPELINE_DYNAMIC_STATE2_PCP,
ZINK_PIPELINE_DYNAMIC_VERTEX_INPUT2,
ZINK_PIPELINE_DYNAMIC_VERTEX_INPUT2_PCP,
ZINK_PIPELINE_DYNAMIC_STATE3,
ZINK_PIPELINE_DYNAMIC_STATE3_PCP,
ZINK_PIPELINE_DYNAMIC_VERTEX_INPUT,
ZINK_PIPELINE_DYNAMIC_VERTEX_INPUT_PCP,
} zink_pipeline_dynamic_state;
@ -251,11 +257,8 @@ struct zink_rasterizer_hw_state {
unsigned depth_clip:1;
unsigned pv_last:1;
unsigned line_stipple_enable:1;
unsigned force_persample_interp:1;
unsigned clip_halfz:1;
};
#define ZINK_RAST_HW_STATE_SIZE 9
struct zink_rasterizer_state {
struct pipe_rasterizer_state base;
@ -641,12 +644,19 @@ struct zink_pipeline_dynamic_state2 {
uint16_t vertices_per_patch; //5 bits
};
struct zink_pipeline_dynamic_state3 {
unsigned polygon_mode : 2; //VkPolygonMode
unsigned line_mode : 2; //VkLineRasterizationModeEXT
unsigned depth_clamp:1;
unsigned pv_last:1;
unsigned line_stipple_enable:1;
unsigned clip_halfz:1;
};
struct zink_gfx_pipeline_state {
uint32_t rast_state : ZINK_RAST_HW_STATE_SIZE; //zink_rasterizer_hw_state
uint32_t _pad1 : 6;
uint32_t force_persample_interp:1; //duplicated for gpl hashing
/* order matches zink_gfx_output_key: uint16_t offset */
uint32_t rast_samples:8; // 2 extra bits (can be used for new members)
/* order matches zink_gfx_output_key */
unsigned force_persample_interp:1;
uint32_t rast_samples:23; //17 extra bits
uint32_t min_samples:6;
uint32_t feedback_loop : 1;
uint32_t feedback_loop_zs : 1;
@ -662,9 +672,8 @@ struct zink_gfx_pipeline_state {
struct zink_pipeline_dynamic_state1 dyn_state1;
struct zink_pipeline_dynamic_state2 dyn_state2;
struct zink_pipeline_dynamic_state3 dyn_state3;
uint32_t _pad;
uint32_t gkey; //for pipeline library lookups
union {
VkShaderModule modules[MESA_SHADER_STAGES - 1];
uint32_t optimal_key;
@ -776,7 +785,6 @@ struct zink_program {
typedef bool (*equals_gfx_pipeline_state_func)(const void *a, const void *b);
struct zink_gfx_library_key {
uint32_t hw_rast_state;
union {
VkShaderModule modules[ZINK_GFX_SHADER_COUNT];
uint32_t optimal_key; //equals_pipeline_lib_optimal
@ -799,14 +807,15 @@ struct zink_gfx_input_key {
};
struct zink_gfx_output_key {
uint32_t _pad:15;
uint32_t force_persample_interp:1;
uint32_t rast_samples:8; // 2 extra bits (can be used for new members)
/* order matches zink_gfx_output_key */
unsigned force_persample_interp:1;
uint32_t rast_samples:23; //17 extra bits
uint32_t min_samples:6;
uint32_t feedback_loop : 1;
uint32_t feedback_loop_zs : 1;
VkSampleMask sample_mask;
/* TODO: compress these */
unsigned rp_state;
uint32_t blend_id;
VkPipeline pipeline;
@ -838,7 +847,7 @@ struct zink_gfx_program {
uint32_t last_finalized_hash[2][4]; //[dynamic, renderpass][primtype idx]
VkPipeline last_pipeline[2][4]; //[dynamic, renderpass][primtype idx]
struct set libs[4]; //zink_gfx_library_key[primtype] -> VkPipeline
struct set libs; //zink_gfx_library_key -> VkPipeline
};
struct zink_compute_program {