mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-23 17:40:11 +01:00
zink: implement mesh shaders
this reuses some of the machinery from regular gfx shaders, but there are some key differences: * separate program/GPL caching * separate GPL vertex input (technically illegal because spec hasn't caught up) * in descriptor layouts, task+mesh occupy vs+tcs space (and thus vs+tcs layouts add mesh stages) * lots of 'is_mesh' checks sprinkled all over otherwise much of this change is just enlarging arrays Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/37427>
This commit is contained in:
parent
a9b1a6d54a
commit
c39123c74d
20 changed files with 996 additions and 244 deletions
|
|
@ -74,3 +74,10 @@ KHR-GL46.packed_pixels.varied_rectangle.rgb4_format_green
|
||||||
spec@!opengl 1.1@copypixels-sync
|
spec@!opengl 1.1@copypixels-sync
|
||||||
spec@amd_pinned_memory@map-buffer offset=0
|
spec@amd_pinned_memory@map-buffer offset=0
|
||||||
spec@glsl-1.30@execution@texelfetch fs sampler2darray 98x1x9-98x129x9
|
spec@glsl-1.30@execution@texelfetch fs sampler2darray 98x1x9-98x129x9
|
||||||
|
|
||||||
|
|
||||||
|
# mesh shaders somehow?
|
||||||
|
glx@glx-visuals-depth
|
||||||
|
glx@glx-visuals-depth -pixmap
|
||||||
|
glx@glx-visuals-stencil
|
||||||
|
glx@glx-visuals-stencil -pixmap
|
||||||
|
|
|
||||||
|
|
@ -221,3 +221,7 @@ spec@glsl-1.50@gs-max-output
|
||||||
spec@glsl-4.30@execution@built-in-functions@cs-clamp-ivec4-ivec4-ivec4
|
spec@glsl-4.30@execution@built-in-functions@cs-clamp-ivec4-ivec4-ivec4
|
||||||
spec@oes_texture_view@rendering-formats
|
spec@oes_texture_view@rendering-formats
|
||||||
spec@ovr_multiview@triangle_compare_max_basemax_layersmax
|
spec@ovr_multiview@triangle_compare_max_basemax_layersmax
|
||||||
|
|
||||||
|
# mesh shaders somehow?
|
||||||
|
glx@glx-visuals-depth
|
||||||
|
glx@glx-visuals-stencil
|
||||||
|
|
|
||||||
|
|
@ -105,3 +105,11 @@ spec@ext_texture_lod_bias@lodbias
|
||||||
spec@glsl-1.30@execution@texelfetch fs sampler1darray 1x71-501x71
|
spec@glsl-1.30@execution@texelfetch fs sampler1darray 1x71-501x71
|
||||||
spec@glsl-1.30@execution@texelfetch fs sampler2d 1x71-501x71
|
spec@glsl-1.30@execution@texelfetch fs sampler2d 1x71-501x71
|
||||||
spec@glsl-1.30@execution@texelfetch fs sampler2darray 1x129x9-98x129x9
|
spec@glsl-1.30@execution@texelfetch fs sampler2darray 1x129x9-98x129x9
|
||||||
|
|
||||||
|
|
||||||
|
# mesh shaders somehow?
|
||||||
|
glx@glx-visuals-depth
|
||||||
|
glx@glx-visuals-depth -pixmap
|
||||||
|
glx@glx-visuals-stencil
|
||||||
|
glx@glx-visuals-stencil -pixmap
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -421,3 +421,9 @@ KHR-GL46.transform_feedback_overflow_query_ARB.multiple-streams-one-buffer-per-s
|
||||||
dEQP-GLES31.functional.copy_image.mixed.viewclass_64_bits_mixed.rg32f_r11_eac.texture3d_to_cubemap
|
dEQP-GLES31.functional.copy_image.mixed.viewclass_64_bits_mixed.rg32f_r11_eac.texture3d_to_cubemap
|
||||||
shaders@glsl-fs-loop
|
shaders@glsl-fs-loop
|
||||||
spec@arb_gpu_shader5@texturegather@vs-rgba-3-unorm-2d
|
spec@arb_gpu_shader5@texturegather@vs-rgba-3-unorm-2d
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# mesh shaders somehow?
|
||||||
|
glx@glx-visuals-stencil
|
||||||
|
glx@glx-visuals-stencil -pixmap
|
||||||
|
|
|
||||||
|
|
@ -3320,7 +3320,7 @@ zink_shader_spirv_compile(struct zink_screen *screen, struct zink_shader *zs, st
|
||||||
sci.pSetLayouts = pg->dsl;
|
sci.pSetLayouts = pg->dsl;
|
||||||
} else {
|
} else {
|
||||||
sci.setLayoutCount = zs->info.stage == MESA_SHADER_COMPUTE ? 1 : ZINK_GFX_SHADER_COUNT;
|
sci.setLayoutCount = zs->info.stage == MESA_SHADER_COMPUTE ? 1 : ZINK_GFX_SHADER_COUNT;
|
||||||
dsl[zs->info.stage] = zs->precompile.dsl;;
|
dsl[zink_descriptor_stage_idx(zs->info.stage)] = zs->precompile.dsl;;
|
||||||
sci.pSetLayouts = dsl;
|
sci.pSetLayouts = dsl;
|
||||||
}
|
}
|
||||||
VkPushConstantRange pcr;
|
VkPushConstantRange pcr;
|
||||||
|
|
@ -4495,10 +4495,7 @@ zink_binding(mesa_shader_stage stage, VkDescriptorType type, int index, bool com
|
||||||
if (stage == MESA_SHADER_NONE) {
|
if (stage == MESA_SHADER_NONE) {
|
||||||
UNREACHABLE("not supported");
|
UNREACHABLE("not supported");
|
||||||
} else {
|
} else {
|
||||||
unsigned base = stage;
|
unsigned base = zink_descriptor_stage_idx(stage);
|
||||||
/* clamp compute bindings for better driver efficiency */
|
|
||||||
if (mesa_shader_stage_is_compute(stage))
|
|
||||||
base = 0;
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
|
||||||
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
|
||||||
|
|
@ -6291,7 +6288,8 @@ zink_shader_init(struct zink_screen *screen, struct zink_shader *zs)
|
||||||
ztype = ZINK_DESCRIPTOR_TYPE_UBO;
|
ztype = ZINK_DESCRIPTOR_TYPE_UBO;
|
||||||
/* buffer 0 is a push descriptor */
|
/* buffer 0 is a push descriptor */
|
||||||
var->data.descriptor_set = !!var->data.driver_location;
|
var->data.descriptor_set = !!var->data.driver_location;
|
||||||
var->data.binding = !var->data.driver_location ? clamp_stage(&nir->info) :
|
unsigned clamped_stage = mesa_shader_stage_is_compute(nir->info.stage) ? MESA_SHADER_COMPUTE : mesa_shader_stage_is_mesh(nir->info.stage) ? nir->info.stage - MESA_SHADER_TASK : nir->info.stage;
|
||||||
|
var->data.binding = !var->data.driver_location ? clamped_stage :
|
||||||
zink_binding(nir->info.stage,
|
zink_binding(nir->info.stage,
|
||||||
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||||
var->data.driver_location,
|
var->data.driver_location,
|
||||||
|
|
@ -6436,25 +6434,26 @@ gfx_shader_prune(struct zink_screen *screen, struct zink_shader *shader)
|
||||||
if (!prog)
|
if (!prog)
|
||||||
return false;
|
return false;
|
||||||
mesa_shader_stage stage = shader->info.stage;
|
mesa_shader_stage stage = shader->info.stage;
|
||||||
assert(stage < ZINK_GFX_SHADER_COUNT);
|
assert(!mesa_shader_stage_is_compute(stage));
|
||||||
util_queue_fence_wait(&prog->base.cache_fence);
|
util_queue_fence_wait(&prog->base.cache_fence);
|
||||||
unsigned stages_present = prog->stages_present;
|
unsigned stages_present = prog->stages_present;
|
||||||
|
bool is_mesh = (stages_present & BITFIELD_BIT(MESA_SHADER_MESH)) > 0;
|
||||||
unsigned stages_remaining = prog->stages_remaining;
|
unsigned stages_remaining = prog->stages_remaining;
|
||||||
if (prog->shaders[MESA_SHADER_TESS_CTRL] &&
|
if (!is_mesh && prog->shaders[MESA_SHADER_TESS_CTRL] && prog->shaders[MESA_SHADER_TESS_CTRL]->non_fs.is_generated) {
|
||||||
prog->shaders[MESA_SHADER_TESS_CTRL]->non_fs.is_generated) {
|
|
||||||
stages_present &= ~BITFIELD_BIT(MESA_SHADER_TESS_CTRL);
|
stages_present &= ~BITFIELD_BIT(MESA_SHADER_TESS_CTRL);
|
||||||
stages_remaining &= ~BITFIELD_BIT(MESA_SHADER_TESS_CTRL);
|
stages_remaining &= ~BITFIELD_BIT(MESA_SHADER_TESS_CTRL);
|
||||||
}
|
}
|
||||||
unsigned idx = zink_program_cache_stages(stages_present);
|
unsigned idx = is_mesh ? zink_mesh_cache_stages(stages_present) : zink_program_cache_stages(stages_present);
|
||||||
if (!prog->base.removed && stages_present == stages_remaining &&
|
if (!prog->base.removed && stages_present == stages_remaining &&
|
||||||
(stage == MESA_SHADER_FRAGMENT || !shader->non_fs.is_generated)) {
|
(stage == MESA_SHADER_FRAGMENT || !shader->non_fs.is_generated)) {
|
||||||
struct hash_table *ht = &prog->base.ctx->program_cache[idx];
|
struct hash_table *ht = is_mesh ? &prog->base.ctx->mesh_cache[idx] : &prog->base.ctx->program_cache[idx];
|
||||||
simple_mtx_lock(&prog->base.ctx->program_lock[idx]);
|
simple_mtx_t *lock = is_mesh ? &prog->base.ctx->mesh_lock[idx] : &prog->base.ctx->program_lock[idx];
|
||||||
|
simple_mtx_lock(lock);
|
||||||
struct hash_entry *he = _mesa_hash_table_search(ht, prog->shaders);
|
struct hash_entry *he = _mesa_hash_table_search(ht, prog->shaders);
|
||||||
assert(he && he->data == prog);
|
assert(he && he->data == prog);
|
||||||
_mesa_hash_table_remove(ht, he);
|
_mesa_hash_table_remove(ht, he);
|
||||||
prog->base.removed = true;
|
prog->base.removed = true;
|
||||||
simple_mtx_unlock(&prog->base.ctx->program_lock[idx]);
|
simple_mtx_unlock(lock);
|
||||||
|
|
||||||
for (int i = 0; i < ARRAY_SIZE(prog->pipelines); ++i) {
|
for (int i = 0; i < ARRAY_SIZE(prog->pipelines); ++i) {
|
||||||
hash_table_foreach(&prog->pipelines[i], table_entry) {
|
hash_table_foreach(&prog->pipelines[i], table_entry) {
|
||||||
|
|
@ -6473,8 +6472,7 @@ gfx_shader_prune(struct zink_screen *screen, struct zink_shader *shader)
|
||||||
prog->shaders[MESA_SHADER_TESS_CTRL] = NULL;
|
prog->shaders[MESA_SHADER_TESS_CTRL] = NULL;
|
||||||
if (stage != MESA_SHADER_FRAGMENT &&
|
if (stage != MESA_SHADER_FRAGMENT &&
|
||||||
prog->shaders[MESA_SHADER_GEOMETRY] &&
|
prog->shaders[MESA_SHADER_GEOMETRY] &&
|
||||||
prog->shaders[MESA_SHADER_GEOMETRY]->non_fs.parent ==
|
prog->shaders[MESA_SHADER_GEOMETRY]->non_fs.parent == shader) {
|
||||||
shader) {
|
|
||||||
prog->shaders[MESA_SHADER_GEOMETRY] = NULL;
|
prog->shaders[MESA_SHADER_GEOMETRY] = NULL;
|
||||||
}
|
}
|
||||||
zink_gfx_program_reference(screen, &prog, NULL);
|
zink_gfx_program_reference(screen, &prog, NULL);
|
||||||
|
|
@ -6494,10 +6492,17 @@ zink_gfx_shader_free(struct zink_screen *screen, struct zink_shader *shader)
|
||||||
struct zink_gfx_lib_cache *libs = util_dynarray_pop(&shader->pipeline_libs, struct zink_gfx_lib_cache*);
|
struct zink_gfx_lib_cache *libs = util_dynarray_pop(&shader->pipeline_libs, struct zink_gfx_lib_cache*);
|
||||||
if (!libs->removed) {
|
if (!libs->removed) {
|
||||||
libs->removed = true;
|
libs->removed = true;
|
||||||
unsigned idx = zink_program_cache_stages(libs->stages_present);
|
if (libs->stages_present & BITFIELD_BIT(MESA_SHADER_MESH)) {
|
||||||
simple_mtx_lock(&screen->pipeline_libs_lock[idx]);
|
unsigned idx = (libs->stages_present & BITFIELD_BIT(MESA_SHADER_TASK)) > 0;
|
||||||
_mesa_set_remove_key(&screen->pipeline_libs[idx], libs);
|
simple_mtx_lock(&screen->mesh_pipeline_libs_lock[idx]);
|
||||||
simple_mtx_unlock(&screen->pipeline_libs_lock[idx]);
|
_mesa_set_remove_key(&screen->mesh_pipeline_libs[idx], libs);
|
||||||
|
simple_mtx_unlock(&screen->mesh_pipeline_libs_lock[idx]);
|
||||||
|
} else {
|
||||||
|
unsigned idx = zink_program_cache_stages(libs->stages_present);
|
||||||
|
simple_mtx_lock(&screen->pipeline_libs_lock[idx]);
|
||||||
|
_mesa_set_remove_key(&screen->pipeline_libs[idx], libs);
|
||||||
|
simple_mtx_unlock(&screen->pipeline_libs_lock[idx]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
zink_gfx_lib_cache_unref(screen, libs);
|
zink_gfx_lib_cache_unref(screen, libs);
|
||||||
}
|
}
|
||||||
|
|
@ -6507,7 +6512,7 @@ zink_gfx_shader_free(struct zink_screen *screen, struct zink_shader *shader)
|
||||||
zink_gfx_shader_free(screen, shader->non_fs.generated_tcs);
|
zink_gfx_shader_free(screen, shader->non_fs.generated_tcs);
|
||||||
shader->non_fs.generated_tcs = NULL;
|
shader->non_fs.generated_tcs = NULL;
|
||||||
}
|
}
|
||||||
if (shader->info.stage != MESA_SHADER_FRAGMENT) {
|
if (shader->info.stage < MESA_SHADER_FRAGMENT) {
|
||||||
for (unsigned int i = 0; i < ARRAY_SIZE(shader->non_fs.generated_gs); i++) {
|
for (unsigned int i = 0; i < ARRAY_SIZE(shader->non_fs.generated_gs); i++) {
|
||||||
for (int j = 0; j < ARRAY_SIZE(shader->non_fs.generated_gs[0]); j++) {
|
for (int j = 0; j < ARRAY_SIZE(shader->non_fs.generated_gs[0]); j++) {
|
||||||
if (shader->non_fs.generated_gs[i][j]) {
|
if (shader->non_fs.generated_gs[i][j]) {
|
||||||
|
|
|
||||||
|
|
@ -152,6 +152,16 @@ zink_context_destroy(struct pipe_context *pctx)
|
||||||
simple_mtx_unlock((&ctx->program_lock[i]));
|
simple_mtx_unlock((&ctx->program_lock[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < ARRAY_SIZE(ctx->mesh_cache); i++) {
|
||||||
|
simple_mtx_lock((&ctx->mesh_lock[i]));
|
||||||
|
hash_table_foreach(&ctx->mesh_cache[i], entry) {
|
||||||
|
struct zink_program *pg = entry->data;
|
||||||
|
zink_program_finish(ctx, pg);
|
||||||
|
pg->removed = true;
|
||||||
|
}
|
||||||
|
simple_mtx_unlock((&ctx->mesh_lock[i]));
|
||||||
|
}
|
||||||
|
|
||||||
if (ctx->blitter)
|
if (ctx->blitter)
|
||||||
util_blitter_destroy(ctx->blitter);
|
util_blitter_destroy(ctx->blitter);
|
||||||
|
|
||||||
|
|
@ -245,6 +255,10 @@ zink_context_destroy(struct pipe_context *pctx)
|
||||||
_mesa_hash_table_clear(&ctx->program_cache[i], NULL);
|
_mesa_hash_table_clear(&ctx->program_cache[i], NULL);
|
||||||
for (unsigned i = 0; i < ARRAY_SIZE(ctx->program_lock); i++)
|
for (unsigned i = 0; i < ARRAY_SIZE(ctx->program_lock); i++)
|
||||||
simple_mtx_destroy(&ctx->program_lock[i]);
|
simple_mtx_destroy(&ctx->program_lock[i]);
|
||||||
|
for (unsigned i = 0; i < ARRAY_SIZE(ctx->mesh_cache); i++)
|
||||||
|
_mesa_hash_table_clear(&ctx->mesh_cache[i], NULL);
|
||||||
|
for (unsigned i = 0; i < ARRAY_SIZE(ctx->mesh_lock); i++)
|
||||||
|
simple_mtx_destroy(&ctx->mesh_lock[i]);
|
||||||
slab_destroy_child(&ctx->transfer_pool_unsync);
|
slab_destroy_child(&ctx->transfer_pool_unsync);
|
||||||
|
|
||||||
zink_descriptors_deinit(ctx);
|
zink_descriptors_deinit(ctx);
|
||||||
|
|
@ -2246,11 +2260,11 @@ update_feedback_loop_state(struct zink_context *ctx, unsigned idx, unsigned feed
|
||||||
if (feedback_loops != ctx->feedback_loops) {
|
if (feedback_loops != ctx->feedback_loops) {
|
||||||
if (idx == PIPE_MAX_COLOR_BUFS && !zink_screen(ctx->base.screen)->driver_workarounds.always_feedback_loop_zs) {
|
if (idx == PIPE_MAX_COLOR_BUFS && !zink_screen(ctx->base.screen)->driver_workarounds.always_feedback_loop_zs) {
|
||||||
if (ctx->gfx_pipeline_state.feedback_loop_zs)
|
if (ctx->gfx_pipeline_state.feedback_loop_zs)
|
||||||
ctx->gfx_pipeline_state.dirty = true;
|
ctx->gfx_pipeline_state.dirty = ctx->gfx_pipeline_state.mesh_dirty = true;
|
||||||
ctx->gfx_pipeline_state.feedback_loop_zs = false;
|
ctx->gfx_pipeline_state.feedback_loop_zs = false;
|
||||||
} else if (idx < PIPE_MAX_COLOR_BUFS && !zink_screen(ctx->base.screen)->driver_workarounds.always_feedback_loop) {
|
} else if (idx < PIPE_MAX_COLOR_BUFS && !zink_screen(ctx->base.screen)->driver_workarounds.always_feedback_loop) {
|
||||||
if (ctx->gfx_pipeline_state.feedback_loop)
|
if (ctx->gfx_pipeline_state.feedback_loop)
|
||||||
ctx->gfx_pipeline_state.dirty = true;
|
ctx->gfx_pipeline_state.dirty = ctx->gfx_pipeline_state.mesh_dirty = true;
|
||||||
ctx->gfx_pipeline_state.feedback_loop = false;
|
ctx->gfx_pipeline_state.feedback_loop = false;
|
||||||
}
|
}
|
||||||
update_feedback_loop_dynamic_state(ctx);
|
update_feedback_loop_dynamic_state(ctx);
|
||||||
|
|
@ -3800,6 +3814,7 @@ flush_batch(struct zink_context *ctx, bool sync)
|
||||||
ctx->dirty_so_targets = true;
|
ctx->dirty_so_targets = true;
|
||||||
memset(ctx->pipeline_changed, 1, sizeof(ctx->pipeline_changed));
|
memset(ctx->pipeline_changed, 1, sizeof(ctx->pipeline_changed));
|
||||||
zink_select_draw_vbo(ctx);
|
zink_select_draw_vbo(ctx);
|
||||||
|
zink_select_draw_mesh_tasks(ctx);
|
||||||
zink_select_launch_grid(ctx);
|
zink_select_launch_grid(ctx);
|
||||||
|
|
||||||
if (ctx->oom_stall)
|
if (ctx->oom_stall)
|
||||||
|
|
@ -3875,11 +3890,11 @@ unbind_fb_surface(struct zink_context *ctx, const struct pipe_surface *surf, uns
|
||||||
if (feedback_loops != ctx->feedback_loops) {
|
if (feedback_loops != ctx->feedback_loops) {
|
||||||
if (idx == PIPE_MAX_COLOR_BUFS && !zink_screen(ctx->base.screen)->driver_workarounds.always_feedback_loop_zs) {
|
if (idx == PIPE_MAX_COLOR_BUFS && !zink_screen(ctx->base.screen)->driver_workarounds.always_feedback_loop_zs) {
|
||||||
if (ctx->gfx_pipeline_state.feedback_loop_zs)
|
if (ctx->gfx_pipeline_state.feedback_loop_zs)
|
||||||
ctx->gfx_pipeline_state.dirty = true;
|
ctx->gfx_pipeline_state.dirty = ctx->gfx_pipeline_state.mesh_dirty = true;
|
||||||
ctx->gfx_pipeline_state.feedback_loop_zs = false;
|
ctx->gfx_pipeline_state.feedback_loop_zs = false;
|
||||||
} else if (idx < PIPE_MAX_COLOR_BUFS && !zink_screen(ctx->base.screen)->driver_workarounds.always_feedback_loop) {
|
} else if (idx < PIPE_MAX_COLOR_BUFS && !zink_screen(ctx->base.screen)->driver_workarounds.always_feedback_loop) {
|
||||||
if (ctx->gfx_pipeline_state.feedback_loop)
|
if (ctx->gfx_pipeline_state.feedback_loop)
|
||||||
ctx->gfx_pipeline_state.dirty = true;
|
ctx->gfx_pipeline_state.dirty = ctx->gfx_pipeline_state.mesh_dirty = true;
|
||||||
ctx->gfx_pipeline_state.feedback_loop = false;
|
ctx->gfx_pipeline_state.feedback_loop = false;
|
||||||
}
|
}
|
||||||
if (zink_screen(ctx->base.screen)->info.have_KHR_unified_image_layouts && zink_screen(ctx->base.screen)->info.have_EXT_attachment_feedback_loop_layout) {
|
if (zink_screen(ctx->base.screen)->info.have_KHR_unified_image_layouts && zink_screen(ctx->base.screen)->info.have_EXT_attachment_feedback_loop_layout) {
|
||||||
|
|
@ -4113,7 +4128,7 @@ zink_set_framebuffer_state(struct pipe_context *pctx,
|
||||||
if (screen->have_full_ds3)
|
if (screen->have_full_ds3)
|
||||||
ctx->sample_mask_changed = true;
|
ctx->sample_mask_changed = true;
|
||||||
else
|
else
|
||||||
ctx->gfx_pipeline_state.dirty = true;
|
ctx->gfx_pipeline_state.dirty = ctx->gfx_pipeline_state.mesh_dirty = true;
|
||||||
}
|
}
|
||||||
ctx->gfx_pipeline_state.rast_samples = rast_samples;
|
ctx->gfx_pipeline_state.rast_samples = rast_samples;
|
||||||
|
|
||||||
|
|
@ -4146,7 +4161,7 @@ zink_set_sample_mask(struct pipe_context *pctx, unsigned sample_mask)
|
||||||
if (zink_screen(pctx->screen)->have_full_ds3)
|
if (zink_screen(pctx->screen)->have_full_ds3)
|
||||||
ctx->sample_mask_changed = true;
|
ctx->sample_mask_changed = true;
|
||||||
else
|
else
|
||||||
ctx->gfx_pipeline_state.dirty = true;
|
ctx->gfx_pipeline_state.dirty = ctx->gfx_pipeline_state.mesh_dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -4154,7 +4169,7 @@ zink_set_min_samples(struct pipe_context *pctx, unsigned min_samples)
|
||||||
{
|
{
|
||||||
struct zink_context *ctx = zink_context(pctx);
|
struct zink_context *ctx = zink_context(pctx);
|
||||||
ctx->gfx_pipeline_state.min_samples = min_samples - 1;
|
ctx->gfx_pipeline_state.min_samples = min_samples - 1;
|
||||||
ctx->gfx_pipeline_state.dirty = true;
|
ctx->gfx_pipeline_state.dirty = ctx->gfx_pipeline_state.mesh_dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -5520,7 +5535,7 @@ zink_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
|
||||||
|
|
||||||
ctx->flags = flags;
|
ctx->flags = flags;
|
||||||
memset(ctx->pipeline_changed, 1, sizeof(ctx->pipeline_changed));
|
memset(ctx->pipeline_changed, 1, sizeof(ctx->pipeline_changed));
|
||||||
ctx->gfx_pipeline_state.dirty = true;
|
ctx->gfx_pipeline_state.dirty = ctx->gfx_pipeline_state.mesh_dirty = true;
|
||||||
ctx->gfx_pipeline_state.dyn_state2.vertices_per_patch = 1;
|
ctx->gfx_pipeline_state.dyn_state2.vertices_per_patch = 1;
|
||||||
ctx->gfx_pipeline_state.uses_dynamic_stride = screen->info.have_EXT_extended_dynamic_state ||
|
ctx->gfx_pipeline_state.uses_dynamic_stride = screen->info.have_EXT_extended_dynamic_state ||
|
||||||
screen->info.have_EXT_vertex_input_dynamic_state;
|
screen->info.have_EXT_vertex_input_dynamic_state;
|
||||||
|
|
@ -5773,7 +5788,7 @@ zink_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!is_copy_only) {
|
if (!is_copy_only) {
|
||||||
for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
|
for (unsigned i = 0; i < MESA_SHADER_MESH_STAGES; i++) {
|
||||||
/* need to update these based on screen config for null descriptors */
|
/* need to update these based on screen config for null descriptors */
|
||||||
for (unsigned j = 0; j < ARRAY_SIZE(ctx->di.t.ubos[i]); j++) {
|
for (unsigned j = 0; j < ARRAY_SIZE(ctx->di.t.ubos[i]); j++) {
|
||||||
if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) {
|
if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) {
|
||||||
|
|
@ -5807,6 +5822,7 @@ zink_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
zink_select_draw_vbo(ctx);
|
zink_select_draw_vbo(ctx);
|
||||||
|
zink_select_draw_mesh_tasks(ctx);
|
||||||
zink_select_launch_grid(ctx);
|
zink_select_launch_grid(ctx);
|
||||||
|
|
||||||
if (!is_copy_only && zink_debug & ZINK_DEBUG_SHADERDB) {
|
if (!is_copy_only && zink_debug & ZINK_DEBUG_SHADERDB) {
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ zink_fb_clear_enabled(const struct zink_context *ctx, unsigned idx)
|
||||||
return ctx->clears_enabled & (PIPE_CLEAR_COLOR0 << idx);
|
return ctx->clears_enabled & (PIPE_CLEAR_COLOR0 << idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t
|
static ALWAYS_INLINE uint32_t
|
||||||
zink_program_cache_stages(uint32_t stages_present)
|
zink_program_cache_stages(uint32_t stages_present)
|
||||||
{
|
{
|
||||||
return (stages_present & ((1 << MESA_SHADER_TESS_CTRL) |
|
return (stages_present & ((1 << MESA_SHADER_TESS_CTRL) |
|
||||||
|
|
@ -70,6 +70,12 @@ zink_program_cache_stages(uint32_t stages_present)
|
||||||
(1 << MESA_SHADER_GEOMETRY))) >> 1;
|
(1 << MESA_SHADER_GEOMETRY))) >> 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ALWAYS_INLINE uint32_t
|
||||||
|
zink_mesh_cache_stages(uint32_t stages_present)
|
||||||
|
{
|
||||||
|
return !!(stages_present & BITFIELD_BIT(MESA_SHADER_TASK));
|
||||||
|
}
|
||||||
|
|
||||||
static ALWAYS_INLINE bool
|
static ALWAYS_INLINE bool
|
||||||
zink_is_zsbuf_used(const struct zink_context *ctx)
|
zink_is_zsbuf_used(const struct zink_context *ctx)
|
||||||
{
|
{
|
||||||
|
|
@ -118,7 +124,8 @@ zink_fence_wait(struct pipe_context *ctx);
|
||||||
static ALWAYS_INLINE void
|
static ALWAYS_INLINE void
|
||||||
zink_update_dirty_gfx_stages(struct zink_context *ctx, uint32_t pstages)
|
zink_update_dirty_gfx_stages(struct zink_context *ctx, uint32_t pstages)
|
||||||
{
|
{
|
||||||
ctx->dirty_gfx_stages |= pstages;
|
ctx->dirty_gfx_stages |= (pstages & BITFIELD_MASK(MESA_SHADER_COMPUTE));
|
||||||
|
ctx->dirty_mesh_stages |= (pstages & (BITFIELD_BIT(MESA_SHADER_FRAGMENT) | BITFIELD_BIT(MESA_SHADER_MESH) | BITFIELD_BIT(MESA_SHADER_TASK)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -195,6 +202,10 @@ zink_pipeline_flags_from_pipe_stage(mesa_shader_stage pstage)
|
||||||
return VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT;
|
return VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT;
|
||||||
case MESA_SHADER_COMPUTE:
|
case MESA_SHADER_COMPUTE:
|
||||||
return VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
|
return VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
|
||||||
|
case MESA_SHADER_TASK:
|
||||||
|
return VK_PIPELINE_STAGE_TASK_SHADER_BIT_EXT;
|
||||||
|
case MESA_SHADER_MESH:
|
||||||
|
return VK_PIPELINE_STAGE_MESH_SHADER_BIT_EXT;
|
||||||
default:
|
default:
|
||||||
UNREACHABLE("unknown shader stage");
|
UNREACHABLE("unknown shader stage");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -249,6 +249,8 @@ create_gfx_layout(struct zink_context *ctx, struct zink_descriptor_layout_key **
|
||||||
VkDescriptorType vktype = get_push_types(screen, &dsl_type);
|
VkDescriptorType vktype = get_push_types(screen, &dsl_type);
|
||||||
for (unsigned i = 0; i < ZINK_GFX_SHADER_COUNT; i++) {
|
for (unsigned i = 0; i < ZINK_GFX_SHADER_COUNT; i++) {
|
||||||
unsigned stage_bits = BITFIELD_BIT(i);
|
unsigned stage_bits = BITFIELD_BIT(i);
|
||||||
|
if (i < MESA_SHADER_TESS_EVAL && screen->info.have_EXT_mesh_shader)
|
||||||
|
stage_bits |= BITFIELD_BIT(i + MESA_SHADER_TASK);
|
||||||
init_push_binding(&bindings[i], i, stage_bits, vktype);
|
init_push_binding(&bindings[i], i, stage_bits, vktype);
|
||||||
}
|
}
|
||||||
if (fbfetch) {
|
if (fbfetch) {
|
||||||
|
|
@ -657,10 +659,11 @@ zink_descriptor_program_init(struct zink_context *ctx, struct zink_program *pg)
|
||||||
for (unsigned i = 0; i < ZINK_DESCRIPTOR_BASE_TYPES; i++)
|
for (unsigned i = 0; i < ZINK_DESCRIPTOR_BASE_TYPES; i++)
|
||||||
wd_count[i + 1] = pg->dd.pool_key[i] ? pg->dd.pool_key[i]->layout->num_bindings : 0;
|
wd_count[i + 1] = pg->dd.pool_key[i] ? pg->dd.pool_key[i]->layout->num_bindings : 0;
|
||||||
|
|
||||||
enum zink_pipeline_idx pidx = pg->is_compute ? ZINK_PIPELINE_COMPUTE : ZINK_PIPELINE_GFX;
|
enum zink_pipeline_idx pidx = pg->is_compute ? ZINK_PIPELINE_COMPUTE : stages[MESA_SHADER_VERTEX]? ZINK_PIPELINE_GFX : ZINK_PIPELINE_MESH;
|
||||||
VkDescriptorUpdateTemplateEntry *push_entries[] = {
|
VkDescriptorUpdateTemplateEntry *push_entries[] = {
|
||||||
ctx->dd.push_entries,
|
ctx->dd.push_entries,
|
||||||
&ctx->dd.compute_push_entry,
|
&ctx->dd.compute_push_entry,
|
||||||
|
ctx->dd.mesh_push_entries,
|
||||||
};
|
};
|
||||||
for (unsigned i = 0; i < pg->num_dsl; i++) {
|
for (unsigned i = 0; i < pg->num_dsl; i++) {
|
||||||
bool is_push = i == 0;
|
bool is_push = i == 0;
|
||||||
|
|
@ -1173,7 +1176,7 @@ zink_descriptors_update_masked_buffer(struct zink_context *ctx, enum zink_pipeli
|
||||||
struct zink_screen *screen = zink_screen(ctx->base.screen);
|
struct zink_screen *screen = zink_screen(ctx->base.screen);
|
||||||
struct zink_batch_state *bs = ctx->bs;
|
struct zink_batch_state *bs = ctx->bs;
|
||||||
bool is_compute = pidx == ZINK_PIPELINE_COMPUTE;
|
bool is_compute = pidx == ZINK_PIPELINE_COMPUTE;
|
||||||
struct zink_program *pg = is_compute ? &ctx->curr_compute->base : &ctx->curr_program->base;
|
struct zink_program *pg = is_compute ? &ctx->curr_compute->base : pidx == ZINK_PIPELINE_GFX ? &ctx->curr_program->base : &ctx->mesh_program->base;
|
||||||
|
|
||||||
/* skip if no descriptors are updated */
|
/* skip if no descriptors are updated */
|
||||||
if (!pg->dd.binding_usage || (!changed_sets && !bind_sets))
|
if (!pg->dd.binding_usage || (!changed_sets && !bind_sets))
|
||||||
|
|
@ -1249,7 +1252,7 @@ zink_descriptors_update_masked(struct zink_context *ctx, enum zink_pipeline_idx
|
||||||
struct zink_screen *screen = zink_screen(ctx->base.screen);
|
struct zink_screen *screen = zink_screen(ctx->base.screen);
|
||||||
struct zink_batch_state *bs = ctx->bs;
|
struct zink_batch_state *bs = ctx->bs;
|
||||||
bool is_compute = pidx == ZINK_PIPELINE_COMPUTE;
|
bool is_compute = pidx == ZINK_PIPELINE_COMPUTE;
|
||||||
struct zink_program *pg = is_compute ? &ctx->curr_compute->base : &ctx->curr_program->base;
|
struct zink_program *pg = is_compute ? &ctx->curr_compute->base : pidx == ZINK_PIPELINE_GFX ? &ctx->curr_program->base : &ctx->mesh_program->base;
|
||||||
VkDescriptorSet desc_sets[ZINK_DESCRIPTOR_BASE_TYPES];
|
VkDescriptorSet desc_sets[ZINK_DESCRIPTOR_BASE_TYPES];
|
||||||
|
|
||||||
/* skip if no descriptors are updated */
|
/* skip if no descriptors are updated */
|
||||||
|
|
@ -1321,7 +1324,8 @@ zink_descriptors_update(struct zink_context *ctx, enum zink_pipeline_idx pidx)
|
||||||
{
|
{
|
||||||
struct zink_batch_state *bs = ctx->bs;
|
struct zink_batch_state *bs = ctx->bs;
|
||||||
bool is_compute = pidx == ZINK_PIPELINE_COMPUTE;
|
bool is_compute = pidx == ZINK_PIPELINE_COMPUTE;
|
||||||
struct zink_program *pg = is_compute ? &ctx->curr_compute->base : &ctx->curr_program->base;
|
bool is_mesh = pidx == ZINK_PIPELINE_MESH;
|
||||||
|
struct zink_program *pg = is_compute ? &ctx->curr_compute->base : pidx == ZINK_PIPELINE_GFX ? &ctx->curr_program->base : &ctx->mesh_program->base;
|
||||||
struct zink_screen *screen = zink_screen(ctx->base.screen);
|
struct zink_screen *screen = zink_screen(ctx->base.screen);
|
||||||
bool have_KHR_push_descriptor = screen->info.have_KHR_push_descriptor;
|
bool have_KHR_push_descriptor = screen->info.have_KHR_push_descriptor;
|
||||||
|
|
||||||
|
|
@ -1401,7 +1405,9 @@ zink_descriptors_update(struct zink_context *ctx, enum zink_pipeline_idx pidx)
|
||||||
info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT;
|
info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT;
|
||||||
info.pNext = NULL;
|
info.pNext = NULL;
|
||||||
info.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
info.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||||
info.data.pUniformBuffer = &ctx->di.db.ubos[is_compute ? MESA_SHADER_COMPUTE : i][0];
|
/* mesh push consts pack as VS/TCS */
|
||||||
|
enum mesa_shader_stage stage = is_compute ? MESA_SHADER_COMPUTE : is_mesh && i <= MESA_SHADER_TESS_CTRL ? i + MESA_SHADER_TASK : i;
|
||||||
|
info.data.pUniformBuffer = &ctx->di.db.ubos[stage][0];
|
||||||
uint64_t stage_offset = offset + (is_compute ? 0 : ctx->dd.db_offset[i]);
|
uint64_t stage_offset = offset + (is_compute ? 0 : ctx->dd.db_offset[i]);
|
||||||
VKSCR(GetDescriptorEXT)(screen->dev, &info, screen->info.db_props.robustUniformBufferDescriptorSize,
|
VKSCR(GetDescriptorEXT)(screen->dev, &info, screen->info.db_props.robustUniformBufferDescriptorSize,
|
||||||
bs->dd.db_map + stage_offset);
|
bs->dd.db_map + stage_offset);
|
||||||
|
|
@ -1484,15 +1490,20 @@ zink_context_invalidate_descriptor_state(struct zink_context *ctx, mesa_shader_s
|
||||||
ctx->dd.push_state_changed[ZINK_PIPELINE_COMPUTE] = true;
|
ctx->dd.push_state_changed[ZINK_PIPELINE_COMPUTE] = true;
|
||||||
else if (shader < MESA_SHADER_FRAGMENT)
|
else if (shader < MESA_SHADER_FRAGMENT)
|
||||||
ctx->dd.push_state_changed[ZINK_PIPELINE_GFX] = true;
|
ctx->dd.push_state_changed[ZINK_PIPELINE_GFX] = true;
|
||||||
|
else if (shader > MESA_SHADER_FRAGMENT)
|
||||||
|
ctx->dd.push_state_changed[ZINK_PIPELINE_MESH] = true;
|
||||||
else
|
else
|
||||||
ctx->dd.push_state_changed[ZINK_PIPELINE_GFX] = true;
|
ctx->dd.push_state_changed[ZINK_PIPELINE_GFX] = ctx->dd.push_state_changed[ZINK_PIPELINE_MESH] = true;
|
||||||
} else {
|
} else {
|
||||||
if (shader == MESA_SHADER_COMPUTE)
|
if (shader == MESA_SHADER_COMPUTE)
|
||||||
ctx->dd.state_changed[ZINK_PIPELINE_COMPUTE] |= BITFIELD_BIT(type);
|
ctx->dd.state_changed[ZINK_PIPELINE_COMPUTE] |= BITFIELD_BIT(type);
|
||||||
else if (shader < MESA_SHADER_FRAGMENT)
|
else if (shader < MESA_SHADER_FRAGMENT)
|
||||||
ctx->dd.state_changed[ZINK_PIPELINE_GFX] |= BITFIELD_BIT(type);
|
ctx->dd.state_changed[ZINK_PIPELINE_GFX] |= BITFIELD_BIT(type);
|
||||||
|
else if (shader > MESA_SHADER_FRAGMENT)
|
||||||
|
ctx->dd.state_changed[ZINK_PIPELINE_MESH] |= BITFIELD_BIT(type);
|
||||||
else {
|
else {
|
||||||
ctx->dd.state_changed[ZINK_PIPELINE_GFX] |= BITFIELD_BIT(type);
|
ctx->dd.state_changed[ZINK_PIPELINE_GFX] |= BITFIELD_BIT(type);
|
||||||
|
ctx->dd.state_changed[ZINK_PIPELINE_MESH] |= BITFIELD_BIT(type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1504,8 +1515,10 @@ zink_context_invalidate_descriptor_state_compact(struct zink_context *ctx, mesa_
|
||||||
ctx->dd.push_state_changed[ZINK_PIPELINE_COMPUTE] = true;
|
ctx->dd.push_state_changed[ZINK_PIPELINE_COMPUTE] = true;
|
||||||
else if (shader < MESA_SHADER_FRAGMENT)
|
else if (shader < MESA_SHADER_FRAGMENT)
|
||||||
ctx->dd.push_state_changed[ZINK_PIPELINE_GFX] = true;
|
ctx->dd.push_state_changed[ZINK_PIPELINE_GFX] = true;
|
||||||
|
else if (shader > MESA_SHADER_FRAGMENT)
|
||||||
|
ctx->dd.push_state_changed[ZINK_PIPELINE_MESH] = true;
|
||||||
else
|
else
|
||||||
ctx->dd.push_state_changed[ZINK_PIPELINE_GFX] = true;
|
ctx->dd.push_state_changed[ZINK_PIPELINE_GFX] = ctx->dd.push_state_changed[ZINK_PIPELINE_MESH] = true;
|
||||||
else {
|
else {
|
||||||
if (type > ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW)
|
if (type > ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW)
|
||||||
type -= ZINK_DESCRIPTOR_COMPACT;
|
type -= ZINK_DESCRIPTOR_COMPACT;
|
||||||
|
|
@ -1513,8 +1526,11 @@ zink_context_invalidate_descriptor_state_compact(struct zink_context *ctx, mesa_
|
||||||
ctx->dd.state_changed[ZINK_PIPELINE_COMPUTE] |= BITFIELD_BIT(type);
|
ctx->dd.state_changed[ZINK_PIPELINE_COMPUTE] |= BITFIELD_BIT(type);
|
||||||
else if (shader < MESA_SHADER_FRAGMENT)
|
else if (shader < MESA_SHADER_FRAGMENT)
|
||||||
ctx->dd.state_changed[ZINK_PIPELINE_GFX] |= BITFIELD_BIT(type);
|
ctx->dd.state_changed[ZINK_PIPELINE_GFX] |= BITFIELD_BIT(type);
|
||||||
|
else if (shader > MESA_SHADER_FRAGMENT)
|
||||||
|
ctx->dd.state_changed[ZINK_PIPELINE_MESH] |= BITFIELD_BIT(type);
|
||||||
else {
|
else {
|
||||||
ctx->dd.state_changed[ZINK_PIPELINE_GFX] |= BITFIELD_BIT(type);
|
ctx->dd.state_changed[ZINK_PIPELINE_GFX] |= BITFIELD_BIT(type);
|
||||||
|
ctx->dd.state_changed[ZINK_PIPELINE_MESH] |= BITFIELD_BIT(type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1659,6 +1675,13 @@ zink_descriptors_init(struct zink_context *ctx)
|
||||||
VkDescriptorUpdateTemplateEntry *entry = &ctx->dd.push_entries[i];
|
VkDescriptorUpdateTemplateEntry *entry = &ctx->dd.push_entries[i];
|
||||||
init_push_template_entry(entry, i, i);
|
init_push_template_entry(entry, i, i);
|
||||||
}
|
}
|
||||||
|
/* task+mesh occupy vs+tcs */
|
||||||
|
init_push_template_entry(&ctx->dd.mesh_push_entries[0], zink_descriptor_stage_idx(MESA_SHADER_TASK), MESA_SHADER_TASK);
|
||||||
|
init_push_template_entry(&ctx->dd.mesh_push_entries[1], zink_descriptor_stage_idx(MESA_SHADER_MESH), MESA_SHADER_MESH);
|
||||||
|
for (unsigned i = MESA_SHADER_TESS_EVAL; i < ZINK_GFX_SHADER_COUNT; i++) {
|
||||||
|
VkDescriptorUpdateTemplateEntry *entry = &ctx->dd.mesh_push_entries[i];
|
||||||
|
init_push_template_entry(entry, i, i);
|
||||||
|
}
|
||||||
init_push_template_entry(&ctx->dd.compute_push_entry, MESA_SHADER_COMPUTE, MESA_SHADER_COMPUTE);
|
init_push_template_entry(&ctx->dd.compute_push_entry, MESA_SHADER_COMPUTE, MESA_SHADER_COMPUTE);
|
||||||
VkDescriptorUpdateTemplateEntry *entry = &ctx->dd.push_entries[ZINK_GFX_SHADER_COUNT]; //fbfetch
|
VkDescriptorUpdateTemplateEntry *entry = &ctx->dd.push_entries[ZINK_GFX_SHADER_COUNT]; //fbfetch
|
||||||
entry->dstBinding = ZINK_FBFETCH_BINDING;
|
entry->dstBinding = ZINK_FBFETCH_BINDING;
|
||||||
|
|
|
||||||
|
|
@ -135,6 +135,17 @@ zink_descriptor_type_from_bindless_index(unsigned idx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE static unsigned
|
||||||
|
zink_descriptor_stage_idx(enum mesa_shader_stage stage)
|
||||||
|
{
|
||||||
|
if (stage == MESA_SHADER_TASK || stage == MESA_SHADER_MESH)
|
||||||
|
return stage - MESA_SHADER_TASK;
|
||||||
|
/* clamp compute bindings for better driver efficiency */
|
||||||
|
if (mesa_shader_stage_is_compute(stage))
|
||||||
|
return 0;
|
||||||
|
return stage;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
zink_descriptor_layouts_init(struct zink_screen *screen);
|
zink_descriptor_layouts_init(struct zink_screen *screen);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -267,9 +267,9 @@ update_gfx_pipeline(struct zink_context *ctx, struct zink_batch_state *bs, enum
|
||||||
VkPipeline pipeline = VK_NULL_HANDLE;
|
VkPipeline pipeline = VK_NULL_HANDLE;
|
||||||
if (!ctx->curr_program->base.uses_shobj) {
|
if (!ctx->curr_program->base.uses_shobj) {
|
||||||
if (screen->info.have_EXT_graphics_pipeline_library)
|
if (screen->info.have_EXT_graphics_pipeline_library)
|
||||||
pipeline = zink_get_gfx_pipeline<DYNAMIC_STATE, true>(ctx, ctx->curr_program, &ctx->gfx_pipeline_state, mode);
|
pipeline = zink_get_gfx_pipeline<DYNAMIC_STATE, true, false>(ctx, ctx->curr_program, &ctx->gfx_pipeline_state, mode);
|
||||||
else
|
else
|
||||||
pipeline = zink_get_gfx_pipeline<DYNAMIC_STATE, false>(ctx, ctx->curr_program, &ctx->gfx_pipeline_state, mode);
|
pipeline = zink_get_gfx_pipeline<DYNAMIC_STATE, false, false>(ctx, ctx->curr_program, &ctx->gfx_pipeline_state, mode);
|
||||||
}
|
}
|
||||||
if (pipeline) {
|
if (pipeline) {
|
||||||
pipeline_changed = prev_pipeline != pipeline;
|
pipeline_changed = prev_pipeline != pipeline;
|
||||||
|
|
@ -961,6 +961,180 @@ zink_draw(struct pipe_context *pctx,
|
||||||
|
|
||||||
ctx->last_work_was_compute = false;
|
ctx->last_work_was_compute = false;
|
||||||
ctx->work_count = work_count;
|
ctx->work_count = work_count;
|
||||||
|
if (!ctx->pipeline_changed[ZINK_PIPELINE_MESH]) {
|
||||||
|
ctx->pipeline_changed[ZINK_PIPELINE_MESH] = true;
|
||||||
|
zink_select_draw_mesh_tasks(ctx);
|
||||||
|
}
|
||||||
|
/* flush if there's >100k draws */
|
||||||
|
if (!ctx->unordered_blitting && (unlikely(work_count >= 30000) || ctx->oom_flush))
|
||||||
|
pctx->flush(pctx, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <bool BATCH_CHANGED>
|
||||||
|
static bool
|
||||||
|
update_mesh_pipeline(struct zink_context *ctx, struct zink_batch_state *bs)
|
||||||
|
{
|
||||||
|
VkPipeline prev_pipeline = ctx->gfx_pipeline_state.pipeline;
|
||||||
|
const struct zink_screen *screen = zink_screen(ctx->base.screen);
|
||||||
|
bool shaders_changed = ctx->mesh_dirty || ctx->dirty_mesh_stages;
|
||||||
|
zink_mesh_program_update_optimal(ctx);
|
||||||
|
bool pipeline_changed = false;
|
||||||
|
VkPipeline pipeline = VK_NULL_HANDLE;
|
||||||
|
if (!ctx->mesh_program->base.uses_shobj) {
|
||||||
|
if (screen->info.have_EXT_graphics_pipeline_library)
|
||||||
|
pipeline = zink_get_gfx_pipeline<ZINK_DYNAMIC_STATE3, true, true>(ctx, ctx->mesh_program, &ctx->gfx_pipeline_state, MESA_PRIM_COUNT);
|
||||||
|
else
|
||||||
|
pipeline = zink_get_gfx_pipeline<ZINK_DYNAMIC_STATE3, false, true>(ctx, ctx->mesh_program, &ctx->gfx_pipeline_state, MESA_PRIM_COUNT);
|
||||||
|
}
|
||||||
|
if (pipeline) {
|
||||||
|
pipeline_changed = prev_pipeline != pipeline;
|
||||||
|
if (BATCH_CHANGED || pipeline_changed || ctx->shobj_draw)
|
||||||
|
VKCTX(CmdBindPipeline)(bs->cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||||
|
ctx->shobj_draw = false;
|
||||||
|
} else {
|
||||||
|
if (BATCH_CHANGED || shaders_changed || !ctx->shobj_draw) {
|
||||||
|
VkShaderStageFlagBits stages[] = {
|
||||||
|
VK_SHADER_STAGE_VERTEX_BIT,
|
||||||
|
VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
|
||||||
|
VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
|
||||||
|
VK_SHADER_STAGE_GEOMETRY_BIT,
|
||||||
|
VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||||
|
VK_SHADER_STAGE_FLAG_BITS_MAX_ENUM,
|
||||||
|
VK_SHADER_STAGE_TASK_BIT_EXT,
|
||||||
|
VK_SHADER_STAGE_MESH_BIT_EXT,
|
||||||
|
};
|
||||||
|
/* always rebind all stages */
|
||||||
|
VKCTX(CmdBindShadersEXT)(bs->cmdbuf, ZINK_GFX_SHADER_COUNT, stages, ctx->mesh_program->objects);
|
||||||
|
VKCTX(CmdBindShadersEXT)(bs->cmdbuf, 2, &stages[MESA_SHADER_TASK], &ctx->mesh_program->objects[MESA_SHADER_TASK]);
|
||||||
|
VKCTX(CmdSetSampleLocationsEnableEXT)(bs->cmdbuf, ctx->gfx_pipeline_state.sample_locations_enabled);
|
||||||
|
VKCTX(CmdSetDepthBiasEnable)(bs->cmdbuf, VK_TRUE);
|
||||||
|
pipeline_changed = true;
|
||||||
|
}
|
||||||
|
ctx->shobj_draw = true;
|
||||||
|
}
|
||||||
|
return pipeline_changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <bool BATCH_CHANGED>
|
||||||
|
void
|
||||||
|
zink_draw_mesh_tasks(struct pipe_context *pctx, const struct pipe_grid_info *info)
|
||||||
|
{
|
||||||
|
MESA_TRACE_FUNC();
|
||||||
|
|
||||||
|
struct zink_context *ctx = zink_context(pctx);
|
||||||
|
struct zink_screen *screen = zink_screen(pctx->screen);
|
||||||
|
struct zink_batch_state *bs = ctx->bs;
|
||||||
|
unsigned work_count = ctx->work_count;
|
||||||
|
|
||||||
|
if (ctx->memory_barrier && !ctx->blitting)
|
||||||
|
zink_flush_memory_barrier(ctx, false);
|
||||||
|
|
||||||
|
if (unlikely(ctx->buffer_rebind_counter < screen->buffer_rebind_counter && !ctx->blitting)) {
|
||||||
|
ctx->buffer_rebind_counter = screen->buffer_rebind_counter;
|
||||||
|
zink_rebind_all_buffers(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unlikely(ctx->image_rebind_counter < screen->image_rebind_counter && !ctx->blitting)) {
|
||||||
|
ctx->image_rebind_counter = screen->image_rebind_counter;
|
||||||
|
zink_rebind_all_images(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info->indirect) {
|
||||||
|
check_buffer_barrier(ctx, info->indirect,
|
||||||
|
VK_ACCESS_INDIRECT_COMMAND_READ_BIT, VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT);
|
||||||
|
if (info->indirect_draw_count)
|
||||||
|
check_buffer_barrier(ctx, info->indirect_draw_count,
|
||||||
|
VK_ACCESS_INDIRECT_COMMAND_READ_BIT, VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT);
|
||||||
|
}
|
||||||
|
zink_update_barriers(ctx, false, NULL, info->indirect, info->indirect_draw_count);
|
||||||
|
|
||||||
|
if (unlikely(zink_debug & ZINK_DEBUG_SYNC)) {
|
||||||
|
zink_batch_no_rp(ctx);
|
||||||
|
VkMemoryBarrier mb;
|
||||||
|
mb.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
|
||||||
|
mb.pNext = NULL;
|
||||||
|
mb.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
|
||||||
|
mb.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
|
||||||
|
VKSCR(CmdPipelineBarrier)(ctx->bs->cmdbuf,
|
||||||
|
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
||||||
|
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
||||||
|
0, 1, &mb, 0, NULL, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool need_rp_update = !ctx->in_rp || ctx->rp_changed;
|
||||||
|
zink_batch_rp(ctx);
|
||||||
|
/* check dead swapchain */
|
||||||
|
if (unlikely(!ctx->in_rp))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (BATCH_CHANGED)
|
||||||
|
zink_update_descriptor_refs(ctx, false);
|
||||||
|
|
||||||
|
bool pipeline_changed = need_rp_update || ctx->mesh_dirty || ctx->dirty_mesh_stages || BATCH_CHANGED ?
|
||||||
|
update_mesh_pipeline<BATCH_CHANGED>(ctx, bs) :
|
||||||
|
false;
|
||||||
|
|
||||||
|
emit_dynamic_state<ZINK_DYNAMIC_STATE3, BATCH_CHANGED>(ctx, pipeline_changed, ctx->vp_state.mesh_num_viewports);
|
||||||
|
|
||||||
|
struct zink_rasterizer_state *rast_state = ctx->rast_state;
|
||||||
|
bool using_depth_bias = !!rast_state->offset_fill;
|
||||||
|
if (BATCH_CHANGED || using_depth_bias != ctx->was_using_depth_bias || ctx->depth_bias_changed) {
|
||||||
|
if (using_depth_bias) {
|
||||||
|
VKCTX(CmdSetDepthBias)(bs->cmdbuf, rast_state->offset_units, rast_state->offset_clamp, rast_state->offset_scale);
|
||||||
|
} else {
|
||||||
|
VKCTX(CmdSetDepthBias)(bs->cmdbuf, 0.0f, 0.0f, 0.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ctx->was_using_depth_bias = using_depth_bias;
|
||||||
|
ctx->depth_bias_changed = false;
|
||||||
|
|
||||||
|
if (zink_program_has_descriptors(&ctx->mesh_program->base) && (BATCH_CHANGED || ctx->dd.push_state_changed[ZINK_PIPELINE_MESH] || ctx->dd.state_changed[ZINK_PIPELINE_MESH] || pipeline_changed))
|
||||||
|
zink_descriptors_update(ctx, ZINK_PIPELINE_MESH);
|
||||||
|
|
||||||
|
if (ctx->di.any_bindless_dirty &&
|
||||||
|
/* some apps (d3dretrace) call MakeTextureHandleResidentARB randomly */
|
||||||
|
zink_program_has_descriptors(&ctx->mesh_program->base) &&
|
||||||
|
ctx->mesh_program->base.dd.bindless)
|
||||||
|
zink_descriptors_update_bindless(ctx);
|
||||||
|
|
||||||
|
if (BATCH_CHANGED) {
|
||||||
|
ctx->pipeline_changed[ZINK_PIPELINE_MESH] = false;
|
||||||
|
zink_select_draw_mesh_tasks(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool marker = false;
|
||||||
|
if (unlikely(zink_tracing)) {
|
||||||
|
marker = zink_cmd_debug_marker_begin(ctx, VK_NULL_HANDLE, "draw_mesh(%u cbufs|%s, %dx%d)",
|
||||||
|
ctx->fb_state.nr_cbufs,
|
||||||
|
ctx->fb_state.zsbuf.texture ? "zsbuf" : "",
|
||||||
|
lround(ctx->fb_state.width), lround(ctx->fb_state.height));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info->indirect) {
|
||||||
|
struct zink_resource *indirect = zink_resource(info->indirect);
|
||||||
|
zink_batch_reference_resource_rw(ctx, indirect, false);
|
||||||
|
if (info->indirect_draw_count) {
|
||||||
|
struct zink_resource *indirect_draw_count = zink_resource(info->indirect_draw_count);
|
||||||
|
zink_batch_reference_resource_rw(ctx, indirect_draw_count, false);
|
||||||
|
VKCTX(CmdDrawMeshTasksIndirectCountEXT)(bs->cmdbuf, indirect->obj->buffer, info->indirect_offset,
|
||||||
|
indirect_draw_count->obj->buffer, info->indirect_draw_count_offset,
|
||||||
|
info->draw_count, info->indirect_stride);
|
||||||
|
} else
|
||||||
|
VKCTX(CmdDrawMeshTasksIndirectEXT)(bs->cmdbuf, indirect->obj->buffer, info->indirect_offset, info->draw_count, info->indirect_stride);
|
||||||
|
} else {
|
||||||
|
VKCTX(CmdDrawMeshTasksEXT)(bs->cmdbuf, info->grid[0], info->grid[1], info->grid[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unlikely(zink_tracing))
|
||||||
|
zink_cmd_debug_marker_end(ctx, bs->cmdbuf, marker);
|
||||||
|
|
||||||
|
ctx->last_work_was_compute = false;
|
||||||
|
ctx->work_count++;
|
||||||
|
if (!ctx->pipeline_changed[ZINK_PIPELINE_GFX]) {
|
||||||
|
ctx->pipeline_changed[ZINK_PIPELINE_GFX] = true;
|
||||||
|
zink_select_draw_vbo(ctx);
|
||||||
|
}
|
||||||
/* flush if there's >100k draws */
|
/* flush if there's >100k draws */
|
||||||
if (!ctx->unordered_blitting && (unlikely(work_count >= 30000) || ctx->oom_flush))
|
if (!ctx->unordered_blitting && (unlikely(work_count >= 30000) || ctx->oom_flush))
|
||||||
pctx->flush(pctx, NULL, 0);
|
pctx->flush(pctx, NULL, 0);
|
||||||
|
|
@ -1222,6 +1396,12 @@ zink_invalid_draw_vbo(struct pipe_context *pipe,
|
||||||
UNREACHABLE("vertex shader not bound");
|
UNREACHABLE("vertex shader not bound");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
zink_invalid_draw_mesh_tasks(struct pipe_context *pctx, const struct pipe_grid_info *dinfo)
|
||||||
|
{
|
||||||
|
UNREACHABLE("mesh shader not bound");
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
zink_invalid_draw_vertex_state(struct pipe_context *pipe,
|
zink_invalid_draw_vertex_state(struct pipe_context *pipe,
|
||||||
struct pipe_vertex_state *vstate,
|
struct pipe_vertex_state *vstate,
|
||||||
|
|
@ -1303,6 +1483,35 @@ equals_gfx_program(const void *a, const void *b)
|
||||||
return !memcmp(a, b, sizeof(void*) * ZINK_GFX_SHADER_COUNT);
|
return !memcmp(a, b, sizeof(void*) * ZINK_GFX_SHADER_COUNT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <unsigned HAS_TASK>
|
||||||
|
static uint32_t
|
||||||
|
hash_mesh_program(const void *key)
|
||||||
|
{
|
||||||
|
const struct zink_shader **shaders = (const struct zink_shader**)key;
|
||||||
|
uint32_t base_hash = shaders[MESA_SHADER_MESH]->hash ^ shaders[MESA_SHADER_FRAGMENT]->hash;
|
||||||
|
if (HAS_TASK == 0) //MS+FS
|
||||||
|
return base_hash;
|
||||||
|
//TS+MS+FS
|
||||||
|
return base_hash ^ shaders[MESA_SHADER_TASK]->hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <unsigned HAS_TASK>
|
||||||
|
static bool
|
||||||
|
equals_mesh_program(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
const void **sa = (const void**)a;
|
||||||
|
const void **sb = (const void**)b;
|
||||||
|
STATIC_ASSERT(MESA_SHADER_TASK == 6);
|
||||||
|
STATIC_ASSERT(MESA_SHADER_MESH == 7);
|
||||||
|
STATIC_ASSERT(MESA_SHADER_FRAGMENT == 4);
|
||||||
|
if (HAS_TASK == 0) //MS+FS
|
||||||
|
return sa[MESA_SHADER_MESH] == sb[MESA_SHADER_MESH] &&
|
||||||
|
sa[MESA_SHADER_FRAGMENT] == sb[MESA_SHADER_FRAGMENT];
|
||||||
|
//TS+MS+FS
|
||||||
|
return sa[MESA_SHADER_FRAGMENT] == sb[MESA_SHADER_FRAGMENT] &&
|
||||||
|
!memcmp(&sa[MESA_SHADER_TASK], &sb[MESA_SHADER_TASK], sizeof(void*) * 2);
|
||||||
|
}
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
void
|
void
|
||||||
zink_init_draw_functions(struct zink_context *ctx, struct zink_screen *screen)
|
zink_init_draw_functions(struct zink_context *ctx, struct zink_screen *screen)
|
||||||
|
|
@ -1355,6 +1564,15 @@ zink_init_draw_functions(struct zink_context *ctx, struct zink_screen *screen)
|
||||||
_mesa_hash_table_init(&ctx->program_cache[7], ctx, hash_gfx_program<7>, equals_gfx_program<7>);
|
_mesa_hash_table_init(&ctx->program_cache[7], ctx, hash_gfx_program<7>, equals_gfx_program<7>);
|
||||||
for (unsigned i = 0; i < ARRAY_SIZE(ctx->program_lock); i++)
|
for (unsigned i = 0; i < ARRAY_SIZE(ctx->program_lock); i++)
|
||||||
simple_mtx_init(&ctx->program_lock[i], mtx_plain);
|
simple_mtx_init(&ctx->program_lock[i], mtx_plain);
|
||||||
|
|
||||||
|
ctx->base.draw_mesh_tasks = zink_draw_mesh_tasks<true>;
|
||||||
|
_mesa_hash_table_init(&ctx->mesh_cache[0], ctx, hash_mesh_program<0>, equals_mesh_program<0>);
|
||||||
|
_mesa_hash_table_init(&ctx->mesh_cache[1], ctx, hash_mesh_program<1>, equals_mesh_program<1>);
|
||||||
|
for (unsigned i = 0; i < ARRAY_SIZE(ctx->mesh_lock); i++)
|
||||||
|
simple_mtx_init(&ctx->mesh_lock[i], mtx_plain);
|
||||||
|
ctx->draw_mesh_tasks[0] = zink_draw_mesh_tasks<false>;
|
||||||
|
ctx->draw_mesh_tasks[1] = zink_draw_mesh_tasks<true>;
|
||||||
|
ctx->base.draw_mesh_tasks = zink_invalid_draw_mesh_tasks;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -1380,4 +1598,9 @@ zink_init_screen_pipeline_libs(struct zink_screen *screen)
|
||||||
_mesa_set_init(&screen->pipeline_libs[7], NULL, hash_gfx_program<7>, equals_gfx_program<7>);
|
_mesa_set_init(&screen->pipeline_libs[7], NULL, hash_gfx_program<7>, equals_gfx_program<7>);
|
||||||
for (unsigned i = 0; i < ARRAY_SIZE(screen->pipeline_libs_lock); i++)
|
for (unsigned i = 0; i < ARRAY_SIZE(screen->pipeline_libs_lock); i++)
|
||||||
simple_mtx_init(&screen->pipeline_libs_lock[i], mtx_plain);
|
simple_mtx_init(&screen->pipeline_libs_lock[i], mtx_plain);
|
||||||
|
|
||||||
|
_mesa_set_init(&screen->mesh_pipeline_libs[0], NULL, hash_mesh_program<0>, equals_mesh_program<0>);
|
||||||
|
_mesa_set_init(&screen->mesh_pipeline_libs[1], NULL, hash_mesh_program<1>, equals_mesh_program<1>);
|
||||||
|
for (unsigned i = 0; i < ARRAY_SIZE(screen->mesh_pipeline_libs_lock); i++)
|
||||||
|
simple_mtx_init(&screen->mesh_pipeline_libs_lock[i], mtx_plain);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,16 +5,23 @@
|
||||||
static inline void
|
static inline void
|
||||||
zink_select_draw_vbo(struct zink_context *ctx)
|
zink_select_draw_vbo(struct zink_context *ctx)
|
||||||
{
|
{
|
||||||
ctx->base.draw_vbo = ctx->draw_vbo[ctx->pipeline_changed[0]];
|
ctx->base.draw_vbo = ctx->draw_vbo[ctx->pipeline_changed[ZINK_PIPELINE_GFX]];
|
||||||
ctx->base.draw_vertex_state = ctx->draw_state[ctx->pipeline_changed[0]];
|
ctx->base.draw_vertex_state = ctx->draw_state[ctx->pipeline_changed[ZINK_PIPELINE_GFX]];
|
||||||
assert(ctx->base.draw_vbo);
|
assert(ctx->base.draw_vbo);
|
||||||
assert(ctx->base.draw_vertex_state);
|
assert(ctx->base.draw_vertex_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
zink_select_draw_mesh_tasks(struct zink_context *ctx)
|
||||||
|
{
|
||||||
|
ctx->base.draw_mesh_tasks = ctx->draw_mesh_tasks[ctx->pipeline_changed[ZINK_PIPELINE_MESH]];
|
||||||
|
assert(ctx->base.draw_mesh_tasks);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
zink_select_launch_grid(struct zink_context *ctx)
|
zink_select_launch_grid(struct zink_context *ctx)
|
||||||
{
|
{
|
||||||
ctx->base.launch_grid = ctx->launch_grid[ctx->pipeline_changed[1]];
|
ctx->base.launch_grid = ctx->launch_grid[ctx->pipeline_changed[ZINK_PIPELINE_COMPUTE]];
|
||||||
assert(ctx->base.launch_grid);
|
assert(ctx->base.launch_grid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,8 @@
|
||||||
#include "util/u_debug.h"
|
#include "util/u_debug.h"
|
||||||
#include "util/u_prim.h"
|
#include "util/u_prim.h"
|
||||||
|
|
||||||
|
#define GFX_INPUT_MESH 32
|
||||||
|
|
||||||
VkPipeline
|
VkPipeline
|
||||||
zink_create_gfx_pipeline(struct zink_screen *screen,
|
zink_create_gfx_pipeline(struct zink_screen *screen,
|
||||||
struct zink_gfx_program *prog,
|
struct zink_gfx_program *prog,
|
||||||
|
|
@ -47,7 +49,8 @@ zink_create_gfx_pipeline(struct zink_screen *screen,
|
||||||
{
|
{
|
||||||
struct zink_rasterizer_hw_state *hw_rast_state = (void*)&state->dyn_state3;
|
struct zink_rasterizer_hw_state *hw_rast_state = (void*)&state->dyn_state3;
|
||||||
VkPipelineVertexInputStateCreateInfo vertex_input_state;
|
VkPipelineVertexInputStateCreateInfo vertex_input_state;
|
||||||
bool needs_vi = !screen->info.have_EXT_vertex_input_dynamic_state;
|
bool is_mesh = !prog->shaders[MESA_SHADER_VERTEX];
|
||||||
|
bool needs_vi = !screen->info.have_EXT_vertex_input_dynamic_state && !is_mesh;
|
||||||
if (needs_vi) {
|
if (needs_vi) {
|
||||||
memset(&vertex_input_state, 0, sizeof(vertex_input_state));
|
memset(&vertex_input_state, 0, sizeof(vertex_input_state));
|
||||||
vertex_input_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
vertex_input_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
||||||
|
|
@ -76,7 +79,7 @@ zink_create_gfx_pipeline(struct zink_screen *screen,
|
||||||
VkPipelineInputAssemblyStateCreateInfo primitive_state = {0};
|
VkPipelineInputAssemblyStateCreateInfo primitive_state = {0};
|
||||||
primitive_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
primitive_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
||||||
primitive_state.topology = primitive_topology;
|
primitive_state.topology = primitive_topology;
|
||||||
if (!screen->info.have_EXT_extended_dynamic_state2) {
|
if (!screen->info.have_EXT_extended_dynamic_state2 && !is_mesh) {
|
||||||
switch (primitive_topology) {
|
switch (primitive_topology) {
|
||||||
case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
|
case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
|
||||||
case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
|
case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
|
||||||
|
|
@ -226,15 +229,18 @@ zink_create_gfx_pipeline(struct zink_screen *screen,
|
||||||
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_VIEWPORT;
|
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_VIEWPORT;
|
||||||
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_SCISSOR;
|
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_SCISSOR;
|
||||||
}
|
}
|
||||||
if (screen->info.have_EXT_vertex_input_dynamic_state)
|
if (screen->info.have_EXT_extended_dynamic_state2)
|
||||||
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_VERTEX_INPUT_EXT;
|
|
||||||
else if (screen->info.have_EXT_extended_dynamic_state && state->uses_dynamic_stride && state->element_state->num_attribs)
|
|
||||||
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE;
|
|
||||||
if (screen->info.have_EXT_extended_dynamic_state2) {
|
|
||||||
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE;
|
|
||||||
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE;
|
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE;
|
||||||
if (screen->info.dynamic_state2_feats.extendedDynamicState2PatchControlPoints)
|
if (!is_mesh) {
|
||||||
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT;
|
if (screen->info.have_EXT_vertex_input_dynamic_state)
|
||||||
|
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_VERTEX_INPUT_EXT;
|
||||||
|
else if (screen->info.have_EXT_extended_dynamic_state && state->uses_dynamic_stride && state->element_state->num_attribs)
|
||||||
|
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE;
|
||||||
|
if (screen->info.have_EXT_extended_dynamic_state2) {
|
||||||
|
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE;
|
||||||
|
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) {
|
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_CLAMP_ENABLE_EXT;
|
||||||
|
|
@ -270,10 +276,10 @@ zink_create_gfx_pipeline(struct zink_screen *screen,
|
||||||
if (screen->info.have_EXT_color_write_enable)
|
if (screen->info.have_EXT_color_write_enable)
|
||||||
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT;
|
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT;
|
||||||
|
|
||||||
assert(state->rast_prim != MESA_PRIM_COUNT || zink_debug & ZINK_DEBUG_SHADERDB);
|
assert(state->rast_prim != MESA_PRIM_COUNT || zink_debug & ZINK_DEBUG_SHADERDB || is_mesh);
|
||||||
|
|
||||||
VkPipelineRasterizationLineStateCreateInfoEXT rast_line_state;
|
VkPipelineRasterizationLineStateCreateInfoEXT rast_line_state;
|
||||||
if (screen->info.have_EXT_line_rasterization &&
|
if (screen->info.have_EXT_line_rasterization && !is_mesh &&
|
||||||
!state->shader_keys.key[MESA_SHADER_FRAGMENT].key.fs.lower_line_smooth) {
|
!state->shader_keys.key[MESA_SHADER_FRAGMENT].key.fs.lower_line_smooth) {
|
||||||
rast_line_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT;
|
rast_line_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT;
|
||||||
rast_line_state.pNext = rast_state.pNext;
|
rast_line_state.pNext = rast_state.pNext;
|
||||||
|
|
@ -354,9 +360,11 @@ zink_create_gfx_pipeline(struct zink_screen *screen,
|
||||||
pci.flags |= VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT;
|
pci.flags |= VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT;
|
||||||
pci.layout = prog->base.layout;
|
pci.layout = prog->base.layout;
|
||||||
pci.pNext = &state->rendering_info;
|
pci.pNext = &state->rendering_info;
|
||||||
if (needs_vi)
|
if (!is_mesh) {
|
||||||
pci.pVertexInputState = &vertex_input_state;
|
if (needs_vi)
|
||||||
pci.pInputAssemblyState = &primitive_state;
|
pci.pVertexInputState = &vertex_input_state;
|
||||||
|
pci.pInputAssemblyState = &primitive_state;
|
||||||
|
}
|
||||||
pci.pRasterizationState = &rast_state;
|
pci.pRasterizationState = &rast_state;
|
||||||
pci.pColorBlendState = &blend_state;
|
pci.pColorBlendState = &blend_state;
|
||||||
pci.pMultisampleState = &ms_state;
|
pci.pMultisampleState = &ms_state;
|
||||||
|
|
@ -377,10 +385,10 @@ zink_create_gfx_pipeline(struct zink_screen *screen,
|
||||||
tdci.domainOrigin = VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT;
|
tdci.domainOrigin = VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkPipelineShaderStageCreateInfo shader_stages[ZINK_GFX_SHADER_COUNT];
|
VkPipelineShaderStageCreateInfo shader_stages[MESA_SHADER_MESH_STAGES];
|
||||||
VkShaderModuleCreateInfo smci[ZINK_GFX_SHADER_COUNT] = {0};
|
VkShaderModuleCreateInfo smci[MESA_SHADER_MESH_STAGES] = {0};
|
||||||
uint32_t num_stages = 0;
|
uint32_t num_stages = 0;
|
||||||
for (int i = 0; i < ZINK_GFX_SHADER_COUNT; ++i) {
|
for (int i = 0; i < MESA_SHADER_MESH_STAGES; ++i) {
|
||||||
if (!(prog->stages_present & BITFIELD_BIT(i)))
|
if (!(prog->stages_present & BITFIELD_BIT(i)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
@ -691,6 +699,35 @@ zink_create_gfx_pipeline_input(struct zink_screen *screen,
|
||||||
return pipeline;
|
return pipeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VkPipeline
|
||||||
|
zink_create_mesh_pipeline_input(struct zink_screen *screen)
|
||||||
|
{
|
||||||
|
VkGraphicsPipelineLibraryCreateInfoEXT gplci = {
|
||||||
|
VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT,
|
||||||
|
NULL,
|
||||||
|
VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT
|
||||||
|
};
|
||||||
|
|
||||||
|
VkGraphicsPipelineCreateInfo pci = {0};
|
||||||
|
pci.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
||||||
|
pci.pNext = &gplci;
|
||||||
|
pci.flags = VK_PIPELINE_CREATE_LIBRARY_BIT_KHR | VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT;
|
||||||
|
if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB)
|
||||||
|
pci.flags |= VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT;
|
||||||
|
|
||||||
|
VkPipeline pipeline;
|
||||||
|
VkResult result;
|
||||||
|
VRAM_ALLOC_LOOP(result,
|
||||||
|
VKSCR(CreateGraphicsPipelines)(screen->dev, VK_NULL_HANDLE, 1, &pci, NULL, &pipeline),
|
||||||
|
if (result != VK_SUCCESS) {
|
||||||
|
mesa_loge("ZINK: vkCreateGraphicsPipelines failed (%s)", vk_Result_to_str(result));
|
||||||
|
return VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return pipeline;
|
||||||
|
}
|
||||||
|
|
||||||
static VkPipeline
|
static VkPipeline
|
||||||
create_gfx_pipeline_library(struct zink_screen *screen, struct zink_shader_object *objs, unsigned stage_mask, VkPipelineLayout layout, VkPipelineCache pipeline_cache)
|
create_gfx_pipeline_library(struct zink_screen *screen, struct zink_shader_object *objs, unsigned stage_mask, VkPipelineLayout layout, VkPipelineCache pipeline_cache)
|
||||||
{
|
{
|
||||||
|
|
@ -704,7 +741,7 @@ create_gfx_pipeline_library(struct zink_screen *screen, struct zink_shader_objec
|
||||||
&rendering_info,
|
&rendering_info,
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
if (stage_mask & BITFIELD_BIT(MESA_SHADER_VERTEX))
|
if (stage_mask & (BITFIELD_BIT(MESA_SHADER_VERTEX) | BITFIELD_BIT(MESA_SHADER_MESH)))
|
||||||
gplci.flags |= VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT;
|
gplci.flags |= VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT;
|
||||||
if (stage_mask & BITFIELD_BIT(MESA_SHADER_FRAGMENT))
|
if (stage_mask & BITFIELD_BIT(MESA_SHADER_FRAGMENT))
|
||||||
gplci.flags |= VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT;
|
gplci.flags |= VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT;
|
||||||
|
|
@ -743,7 +780,7 @@ create_gfx_pipeline_library(struct zink_screen *screen, struct zink_shader_objec
|
||||||
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_FRONT_FACE;
|
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_FRONT_FACE;
|
||||||
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_CULL_MODE;
|
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_CULL_MODE;
|
||||||
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE;
|
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE;
|
||||||
if (screen->info.dynamic_state2_feats.extendedDynamicState2PatchControlPoints)
|
if (screen->info.dynamic_state2_feats.extendedDynamicState2PatchControlPoints && !(stage_mask & BITFIELD_BIT(MESA_SHADER_MESH)))
|
||||||
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT;
|
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT;
|
||||||
|
|
||||||
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT;
|
dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT;
|
||||||
|
|
@ -794,9 +831,9 @@ create_gfx_pipeline_library(struct zink_screen *screen, struct zink_shader_objec
|
||||||
tdci.domainOrigin = VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT;
|
tdci.domainOrigin = VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkPipelineShaderStageCreateInfo shader_stages[ZINK_GFX_SHADER_COUNT];
|
VkPipelineShaderStageCreateInfo shader_stages[MESA_SHADER_MESH_STAGES];
|
||||||
uint32_t num_stages = 0;
|
uint32_t num_stages = 0;
|
||||||
for (int i = 0; i < ZINK_GFX_SHADER_COUNT; ++i) {
|
for (int i = 0; i < MESA_SHADER_MESH_STAGES; ++i) {
|
||||||
if (!(stage_mask & BITFIELD_BIT(i)))
|
if (!(stage_mask & BITFIELD_BIT(i)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
@ -892,6 +929,21 @@ zink_create_gfx_pipeline_combined(struct zink_screen *screen, struct zink_gfx_pr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* vertex input pipeline library states with mesh: nothing matters */
|
||||||
|
struct zink_gfx_input_key *
|
||||||
|
zink_find_or_create_input_mesh(struct zink_context *ctx)
|
||||||
|
{
|
||||||
|
uint32_t hash = GFX_INPUT_MESH;
|
||||||
|
struct set_entry *he = _mesa_set_search_pre_hashed(&ctx->gfx_inputs, hash, &hash);
|
||||||
|
if (!he) {
|
||||||
|
struct zink_gfx_input_key *ikey = rzalloc(ctx, struct zink_gfx_input_key);
|
||||||
|
ikey->idx = hash;
|
||||||
|
ikey->pipeline = zink_create_mesh_pipeline_input(zink_screen(ctx->base.screen));
|
||||||
|
he = _mesa_set_add_pre_hashed(&ctx->gfx_inputs, hash, ikey);
|
||||||
|
}
|
||||||
|
return (struct zink_gfx_input_key *)he->key;
|
||||||
|
}
|
||||||
|
|
||||||
/* vertex input pipeline library states with dynamic vertex input: only the topology matters */
|
/* vertex input pipeline library states with dynamic vertex input: only the topology matters */
|
||||||
struct zink_gfx_input_key *
|
struct zink_gfx_input_key *
|
||||||
zink_find_or_create_input_dynamic(struct zink_context *ctx, VkPrimitiveTopology vkmode)
|
zink_find_or_create_input_dynamic(struct zink_context *ctx, VkPrimitiveTopology vkmode)
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,8 @@ struct zink_gfx_input_key *
|
||||||
zink_find_or_create_input(struct zink_context *ctx, VkPrimitiveTopology vkmode);
|
zink_find_or_create_input(struct zink_context *ctx, VkPrimitiveTopology vkmode);
|
||||||
struct zink_gfx_input_key *
|
struct zink_gfx_input_key *
|
||||||
zink_find_or_create_input_dynamic(struct zink_context *ctx, VkPrimitiveTopology vkmode);
|
zink_find_or_create_input_dynamic(struct zink_context *ctx, VkPrimitiveTopology vkmode);
|
||||||
|
struct zink_gfx_input_key *
|
||||||
|
zink_find_or_create_input_mesh(struct zink_context *ctx);
|
||||||
|
|
||||||
VkPipeline
|
VkPipeline
|
||||||
zink_create_gfx_pipeline(struct zink_screen *screen,
|
zink_create_gfx_pipeline(struct zink_screen *screen,
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@
|
||||||
static void
|
static void
|
||||||
gfx_program_precompile_job(void *data, void *gdata, int thread_index);
|
gfx_program_precompile_job(void *data, void *gdata, int thread_index);
|
||||||
struct zink_gfx_program *
|
struct zink_gfx_program *
|
||||||
create_gfx_program_separable(struct zink_context *ctx, struct zink_shader **stages, unsigned vertices_per_patch);
|
create_gfx_program_separable(struct zink_context *ctx, struct zink_shader **stages, unsigned vertices_per_patch, bool is_mesh);
|
||||||
|
|
||||||
void
|
void
|
||||||
debug_describe_zink_gfx_program(char *buf, const struct zink_gfx_program *ptr)
|
debug_describe_zink_gfx_program(char *buf, const struct zink_gfx_program *ptr)
|
||||||
|
|
@ -423,6 +423,7 @@ static void
|
||||||
generate_gfx_program_modules(struct zink_context *ctx, struct zink_screen *screen, struct zink_gfx_program *prog, struct zink_gfx_pipeline_state *state)
|
generate_gfx_program_modules(struct zink_context *ctx, struct zink_screen *screen, struct zink_gfx_program *prog, struct zink_gfx_pipeline_state *state)
|
||||||
{
|
{
|
||||||
assert(!prog->objs[MESA_SHADER_VERTEX].mod);
|
assert(!prog->objs[MESA_SHADER_VERTEX].mod);
|
||||||
|
assert(!(prog->stages_present & BITFIELD_BIT(MESA_SHADER_MESH)));
|
||||||
uint32_t variant_hash = 0;
|
uint32_t variant_hash = 0;
|
||||||
bool default_variants = true;
|
bool default_variants = true;
|
||||||
for (unsigned i = 0; i < MESA_SHADER_COMPUTE; i++) {
|
for (unsigned i = 0; i < MESA_SHADER_COMPUTE; i++) {
|
||||||
|
|
@ -458,8 +459,8 @@ generate_gfx_program_modules(struct zink_context *ctx, struct zink_screen *scree
|
||||||
static void
|
static void
|
||||||
generate_gfx_program_modules_optimal(struct zink_context *ctx, struct zink_screen *screen, struct zink_gfx_program *prog, struct zink_gfx_pipeline_state *state)
|
generate_gfx_program_modules_optimal(struct zink_context *ctx, struct zink_screen *screen, struct zink_gfx_program *prog, struct zink_gfx_pipeline_state *state)
|
||||||
{
|
{
|
||||||
assert(!prog->objs[MESA_SHADER_VERTEX].mod);
|
assert(!prog->objs[MESA_SHADER_VERTEX].mod && !prog->objs[MESA_SHADER_MESH].mod);
|
||||||
for (unsigned i = 0; i < MESA_SHADER_COMPUTE; i++) {
|
for (unsigned i = 0; i < MESA_SHADER_MESH_STAGES; i++) {
|
||||||
if (!(prog->stages_present & BITFIELD_BIT(i)))
|
if (!(prog->stages_present & BITFIELD_BIT(i)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
@ -470,8 +471,11 @@ generate_gfx_program_modules_optimal(struct zink_context *ctx, struct zink_scree
|
||||||
prog->objects[i] = zm->obj.obj;
|
prog->objects[i] = zm->obj.obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
state->modules_changed = true;
|
if (prog->shaders[MESA_SHADER_VERTEX])
|
||||||
prog->last_variant_hash = state->optimal_key;
|
state->modules_changed = true;
|
||||||
|
else
|
||||||
|
state->mesh_modules_changed = true;
|
||||||
|
prog->last_variant_hash = prog->shaders[MESA_SHADER_MESH] ? state->mesh_optimal_key : state->optimal_key;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t
|
static uint32_t
|
||||||
|
|
@ -488,6 +492,21 @@ equals_pipeline_lib_generated_tcs(const void *a, const void *b)
|
||||||
return !memcmp(a, b, sizeof(uint32_t));
|
return !memcmp(a, b, sizeof(uint32_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t
|
||||||
|
hash_pipeline_lib_mesh(const void *key)
|
||||||
|
{
|
||||||
|
const struct zink_gfx_library_key *gkey = key;
|
||||||
|
return gkey->optimal_key;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
equals_pipeline_lib_mesh(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
const struct zink_gfx_library_key *ak = a;
|
||||||
|
const struct zink_gfx_library_key *bk = b;
|
||||||
|
return ak->optimal_key == bk->optimal_key;
|
||||||
|
}
|
||||||
|
|
||||||
static uint32_t
|
static uint32_t
|
||||||
hash_pipeline_lib(const void *key)
|
hash_pipeline_lib(const void *key)
|
||||||
{
|
{
|
||||||
|
|
@ -631,7 +650,7 @@ zink_gfx_program_update(struct zink_context *ctx)
|
||||||
update_gfx_program(ctx, prog);
|
update_gfx_program(ctx, prog);
|
||||||
} else {
|
} else {
|
||||||
ctx->dirty_gfx_stages |= ctx->shader_stages;
|
ctx->dirty_gfx_stages |= ctx->shader_stages;
|
||||||
prog = zink_create_gfx_program(ctx, ctx->gfx_stages, ctx->gfx_pipeline_state.dyn_state2.vertices_per_patch, hash);
|
prog = zink_create_gfx_program(ctx, ctx->gfx_stages, ctx->gfx_pipeline_state.dyn_state2.vertices_per_patch, hash, false);
|
||||||
zink_screen_get_pipeline_cache(zink_screen(ctx->base.screen), &prog->base, false);
|
zink_screen_get_pipeline_cache(zink_screen(ctx->base.screen), &prog->base, false);
|
||||||
_mesa_hash_table_insert_pre_hashed(ht, hash, prog->shaders, prog);
|
_mesa_hash_table_insert_pre_hashed(ht, hash, prog->shaders, prog);
|
||||||
prog->base.removed = false;
|
prog->base.removed = false;
|
||||||
|
|
@ -702,6 +721,26 @@ update_gfx_program_optimal(struct zink_context *ctx, struct zink_gfx_program *pr
|
||||||
prog->last_variant_hash = ctx->gfx_pipeline_state.optimal_key;
|
prog->last_variant_hash = ctx->gfx_pipeline_state.optimal_key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_mesh_program_optimal(struct zink_context *ctx, struct zink_gfx_program *prog)
|
||||||
|
{
|
||||||
|
const union zink_shader_key_optimal *key = (union zink_shader_key_optimal*)&ctx->gfx_pipeline_state.mesh_optimal_key;
|
||||||
|
const union zink_shader_key_optimal *last_prog_key = (union zink_shader_key_optimal*)&prog->last_variant_hash;
|
||||||
|
const bool shadow_needs_shader_swizzle = last_prog_key->fs.shadow_needs_shader_swizzle && (ctx->dirty_gfx_stages & BITFIELD_BIT(MESA_SHADER_FRAGMENT));
|
||||||
|
if (key->fs_bits != last_prog_key->fs_bits ||
|
||||||
|
/* always recheck shadow swizzles since they aren't directly part of the key */
|
||||||
|
unlikely(shadow_needs_shader_swizzle)) {
|
||||||
|
assert(!prog->is_separable);
|
||||||
|
bool changed = update_gfx_shader_module_optimal(ctx, prog, MESA_SHADER_FRAGMENT);
|
||||||
|
ctx->gfx_pipeline_state.modules_changed |= changed;
|
||||||
|
if (unlikely(shadow_needs_shader_swizzle)) {
|
||||||
|
struct zink_shader_module **pzm = prog->shader_cache[MESA_SHADER_FRAGMENT][0][0].data;
|
||||||
|
ctx->gfx_pipeline_state.shadow = (struct zink_zs_swizzle_key*)pzm[0]->key + sizeof(uint16_t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prog->last_variant_hash = ctx->gfx_pipeline_state.mesh_optimal_key;
|
||||||
|
}
|
||||||
|
|
||||||
static struct zink_gfx_program *
|
static struct zink_gfx_program *
|
||||||
replace_separable_prog(struct zink_context *ctx, struct hash_entry *entry, struct zink_gfx_program *prog)
|
replace_separable_prog(struct zink_context *ctx, struct hash_entry *entry, struct zink_gfx_program *prog)
|
||||||
{
|
{
|
||||||
|
|
@ -709,7 +748,7 @@ replace_separable_prog(struct zink_context *ctx, struct hash_entry *entry, struc
|
||||||
struct zink_gfx_program *real = prog->full_prog ?
|
struct zink_gfx_program *real = prog->full_prog ?
|
||||||
prog->full_prog :
|
prog->full_prog :
|
||||||
/* this will be NULL with ZINK_DEBUG_NOOPT */
|
/* this will be NULL with ZINK_DEBUG_NOOPT */
|
||||||
zink_create_gfx_program(ctx, ctx->gfx_stages, ctx->gfx_pipeline_state.dyn_state2.vertices_per_patch, ctx->gfx_hash);
|
zink_create_gfx_program(ctx, ctx->gfx_stages, ctx->gfx_pipeline_state.dyn_state2.vertices_per_patch, ctx->gfx_hash, false);
|
||||||
entry->data = real;
|
entry->data = real;
|
||||||
entry->key = real->shaders;
|
entry->key = real->shaders;
|
||||||
real->base.removed = false;
|
real->base.removed = false;
|
||||||
|
|
@ -749,7 +788,7 @@ zink_gfx_program_update_optimal(struct zink_context *ctx)
|
||||||
}
|
}
|
||||||
} else if (must_replace) {
|
} else if (must_replace) {
|
||||||
/* this is a non-separable, incompatible prog which needs replacement */
|
/* this is a non-separable, incompatible prog which needs replacement */
|
||||||
struct zink_gfx_program *real = zink_create_gfx_program(ctx, ctx->gfx_stages, ctx->gfx_pipeline_state.dyn_state2.vertices_per_patch, ctx->gfx_hash);
|
struct zink_gfx_program *real = zink_create_gfx_program(ctx, ctx->gfx_stages, ctx->gfx_pipeline_state.dyn_state2.vertices_per_patch, ctx->gfx_hash, false);
|
||||||
generate_gfx_program_modules_optimal(ctx, screen, real, &ctx->gfx_pipeline_state);
|
generate_gfx_program_modules_optimal(ctx, screen, real, &ctx->gfx_pipeline_state);
|
||||||
entry->data = real;
|
entry->data = real;
|
||||||
entry->key = real->shaders;
|
entry->key = real->shaders;
|
||||||
|
|
@ -762,7 +801,7 @@ zink_gfx_program_update_optimal(struct zink_context *ctx)
|
||||||
update_gfx_program_optimal(ctx, prog);
|
update_gfx_program_optimal(ctx, prog);
|
||||||
} else {
|
} else {
|
||||||
ctx->dirty_gfx_stages |= ctx->shader_stages;
|
ctx->dirty_gfx_stages |= ctx->shader_stages;
|
||||||
prog = create_gfx_program_separable(ctx, ctx->gfx_stages, ctx->gfx_pipeline_state.dyn_state2.vertices_per_patch);
|
prog = create_gfx_program_separable(ctx, ctx->gfx_stages, ctx->gfx_pipeline_state.dyn_state2.vertices_per_patch, false);
|
||||||
prog->base.removed = false;
|
prog->base.removed = false;
|
||||||
_mesa_hash_table_insert_pre_hashed(ht, hash, prog->shaders, prog);
|
_mesa_hash_table_insert_pre_hashed(ht, hash, prog->shaders, prog);
|
||||||
if (!prog->is_separable) {
|
if (!prog->is_separable) {
|
||||||
|
|
@ -804,6 +843,90 @@ zink_gfx_program_update_optimal(struct zink_context *ctx)
|
||||||
ctx->last_vertex_stage_dirty = false;
|
ctx->last_vertex_stage_dirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
zink_mesh_program_update_optimal(struct zink_context *ctx)
|
||||||
|
{
|
||||||
|
MESA_TRACE_FUNC();
|
||||||
|
struct zink_screen *screen = zink_screen(ctx->base.screen);
|
||||||
|
struct hash_table *ht = &ctx->mesh_cache[zink_mesh_cache_stages(ctx->shader_stages)];
|
||||||
|
const uint32_t hash = ctx->mesh_hash;
|
||||||
|
simple_mtx_t *lock = &ctx->mesh_lock[zink_mesh_cache_stages(ctx->shader_stages)];
|
||||||
|
assert(ctx->gfx_stages[MESA_SHADER_MESH]);
|
||||||
|
if (ctx->mesh_dirty) {
|
||||||
|
struct zink_gfx_program *prog = NULL;
|
||||||
|
ctx->gfx_pipeline_state.mesh_optimal_key = zink_sanitize_optimal_key_mesh(ctx->gfx_stages, ctx->gfx_pipeline_state.shader_keys_optimal.key.val);
|
||||||
|
simple_mtx_lock(lock);
|
||||||
|
struct hash_entry *entry = _mesa_hash_table_search_pre_hashed(ht, hash, ctx->gfx_stages);
|
||||||
|
|
||||||
|
if (ctx->mesh_program)
|
||||||
|
ctx->gfx_pipeline_state.mesh_final_hash ^= ctx->mesh_program->last_variant_hash;
|
||||||
|
if (entry) {
|
||||||
|
prog = (struct zink_gfx_program*)entry->data;
|
||||||
|
bool must_replace = prog->base.uses_shobj ? !zink_can_use_shader_objects_mesh(ctx) : (prog->is_separable && !zink_can_use_pipeline_libs_mesh(ctx));
|
||||||
|
if (prog->is_separable) {
|
||||||
|
/* shader variants can't be handled by separable programs: sync and compile */
|
||||||
|
if (!ZINK_SHADER_KEY_OPTIMAL_IS_DEFAULT_MESH(ctx->gfx_pipeline_state.mesh_optimal_key) || must_replace)
|
||||||
|
util_queue_fence_wait(&prog->base.cache_fence);
|
||||||
|
/* If the optimized linked pipeline is done compiling, swap it into place. */
|
||||||
|
if (util_queue_fence_is_signalled(&prog->base.cache_fence) &&
|
||||||
|
/* but only if needed for ZINK_DEBUG=noopt */
|
||||||
|
(!(zink_debug & ZINK_DEBUG_NOOPT) || !ZINK_SHADER_KEY_OPTIMAL_IS_DEFAULT_MESH(ctx->gfx_pipeline_state.mesh_optimal_key) || must_replace)) {
|
||||||
|
prog = replace_separable_prog(ctx, entry, prog);
|
||||||
|
}
|
||||||
|
} else if (must_replace) {
|
||||||
|
/* this is a non-separable, incompatible prog which needs replacement */
|
||||||
|
struct zink_gfx_program *real = zink_create_gfx_program(ctx, ctx->gfx_stages, 0, ctx->mesh_hash, true);
|
||||||
|
generate_gfx_program_modules_optimal(ctx, screen, real, &ctx->gfx_pipeline_state);
|
||||||
|
entry->data = real;
|
||||||
|
entry->key = real->shaders;
|
||||||
|
real->base.removed = false;
|
||||||
|
prog->base.removed = true;
|
||||||
|
prog = real;
|
||||||
|
} else if (!prog->base.precompile_done) {
|
||||||
|
util_queue_fence_wait(&prog->base.cache_fence);
|
||||||
|
}
|
||||||
|
update_mesh_program_optimal(ctx, prog);
|
||||||
|
} else {
|
||||||
|
ctx->dirty_gfx_stages |= ctx->shader_stages;
|
||||||
|
prog = create_gfx_program_separable(ctx, ctx->gfx_stages, 0, true);
|
||||||
|
prog->base.removed = false;
|
||||||
|
_mesa_hash_table_insert_pre_hashed(ht, hash, prog->shaders, prog);
|
||||||
|
if (!prog->is_separable) {
|
||||||
|
zink_screen_get_pipeline_cache(screen, &prog->base, false);
|
||||||
|
perf_debug(ctx, "zink[gfx_compile]: new program created (probably legacy GL features in use)\n");
|
||||||
|
generate_gfx_program_modules_optimal(ctx, screen, prog, &ctx->gfx_pipeline_state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
simple_mtx_unlock(lock);
|
||||||
|
if (prog && prog != ctx->mesh_program)
|
||||||
|
zink_batch_reference_program(ctx, &prog->base);
|
||||||
|
ctx->mesh_program = prog;
|
||||||
|
ctx->gfx_pipeline_state.mesh_final_hash ^= ctx->mesh_program->last_variant_hash;
|
||||||
|
} else if (ctx->dirty_mesh_stages) {
|
||||||
|
/* remove old hash */
|
||||||
|
ctx->gfx_pipeline_state.mesh_optimal_key = zink_sanitize_optimal_key_mesh(ctx->gfx_stages, ctx->gfx_pipeline_state.shader_keys_optimal.key.val);
|
||||||
|
ctx->gfx_pipeline_state.mesh_final_hash ^= ctx->mesh_program->last_variant_hash;
|
||||||
|
|
||||||
|
bool must_replace = ctx->mesh_program->base.uses_shobj ? !zink_can_use_shader_objects(ctx) : (ctx->mesh_program->is_separable && !zink_can_use_pipeline_libs(ctx));
|
||||||
|
if (must_replace || (ctx->mesh_program->is_separable && !ZINK_SHADER_KEY_OPTIMAL_IS_DEFAULT_MESH(ctx->gfx_pipeline_state.mesh_optimal_key))) {
|
||||||
|
struct zink_gfx_program *prog = ctx->mesh_program;
|
||||||
|
|
||||||
|
util_queue_fence_wait(&prog->base.cache_fence);
|
||||||
|
/* shader variants can't be handled by separable programs: sync and compile */
|
||||||
|
perf_debug(ctx, "zink[gfx_compile]: non-default shader variant required with separate shader object program\n");
|
||||||
|
simple_mtx_lock(lock);
|
||||||
|
struct hash_entry *entry = _mesa_hash_table_search_pre_hashed(ht, hash, ctx->gfx_stages);
|
||||||
|
ctx->mesh_program = replace_separable_prog(ctx, entry, prog);
|
||||||
|
simple_mtx_unlock(lock);
|
||||||
|
}
|
||||||
|
update_mesh_program_optimal(ctx, ctx->mesh_program);
|
||||||
|
/* apply new hash */
|
||||||
|
ctx->gfx_pipeline_state.mesh_final_hash ^= ctx->mesh_program->last_variant_hash;
|
||||||
|
}
|
||||||
|
ctx->dirty_mesh_stages = 0;
|
||||||
|
ctx->mesh_dirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
optimized_compile_job(void *data, void *gdata, int thread_index)
|
optimized_compile_job(void *data, void *gdata, int thread_index)
|
||||||
{
|
{
|
||||||
|
|
@ -826,8 +949,8 @@ optimized_shobj_compile_job(void *data, void *gdata, int thread_index)
|
||||||
struct zink_gfx_pipeline_cache_entry *pc_entry = data;
|
struct zink_gfx_pipeline_cache_entry *pc_entry = data;
|
||||||
struct zink_screen *screen = gdata;
|
struct zink_screen *screen = gdata;
|
||||||
|
|
||||||
struct zink_shader_object objs[ZINK_GFX_SHADER_COUNT];
|
struct zink_shader_object objs[MESA_SHADER_MESH_STAGES];
|
||||||
for (unsigned i = 0; i < ZINK_GFX_SHADER_COUNT; i++) {
|
for (unsigned i = 0; i < MESA_SHADER_MESH_STAGES; i++) {
|
||||||
objs[i].mod = VK_NULL_HANDLE;
|
objs[i].mod = VK_NULL_HANDLE;
|
||||||
objs[i].spirv = pc_entry->shobjs[i].spirv;
|
objs[i].spirv = pc_entry->shobjs[i].spirv;
|
||||||
}
|
}
|
||||||
|
|
@ -1014,7 +1137,7 @@ create_program(struct zink_context *ctx, bool is_compute)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
assign_io(struct zink_screen *screen,
|
assign_io(struct zink_screen *screen,
|
||||||
nir_shader *shaders[ZINK_GFX_SHADER_COUNT])
|
nir_shader *shaders[MESA_SHADER_MESH_STAGES])
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < MESA_SHADER_FRAGMENT;) {
|
for (unsigned i = 0; i < MESA_SHADER_FRAGMENT;) {
|
||||||
nir_shader *producer = shaders[i];
|
nir_shader *producer = shaders[i];
|
||||||
|
|
@ -1029,6 +1152,19 @@ assign_io(struct zink_screen *screen,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
assign_io_mesh(struct zink_screen *screen,
|
||||||
|
nir_shader *shaders[MESA_SHADER_MESH_STAGES])
|
||||||
|
{
|
||||||
|
nir_shader *producer = shaders[MESA_SHADER_TASK];
|
||||||
|
nir_shader *consumer = shaders[MESA_SHADER_MESH];
|
||||||
|
if (producer)
|
||||||
|
zink_compiler_assign_io(screen, producer, consumer);
|
||||||
|
producer = shaders[MESA_SHADER_MESH];
|
||||||
|
consumer = shaders[MESA_SHADER_FRAGMENT];
|
||||||
|
zink_compiler_assign_io(screen, producer, consumer);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
zink_gfx_lib_cache_unref(struct zink_screen *screen, struct zink_gfx_lib_cache *libs)
|
zink_gfx_lib_cache_unref(struct zink_screen *screen, struct zink_gfx_lib_cache *libs)
|
||||||
{
|
{
|
||||||
|
|
@ -1096,11 +1232,54 @@ find_or_create_lib_cache(struct zink_screen *screen, struct zink_gfx_program *pr
|
||||||
return libs;
|
return libs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct zink_gfx_lib_cache *
|
||||||
|
create_lib_cache_mesh(struct zink_gfx_program *prog)
|
||||||
|
{
|
||||||
|
struct zink_gfx_lib_cache *libs = CALLOC_STRUCT(zink_gfx_lib_cache);
|
||||||
|
libs->stages_present = prog->stages_present;
|
||||||
|
simple_mtx_init(&libs->lock, mtx_plain);
|
||||||
|
_mesa_set_init(&libs->libs, NULL, hash_pipeline_lib_mesh, equals_pipeline_lib_mesh);
|
||||||
|
return libs;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct zink_gfx_lib_cache *
|
||||||
|
find_or_create_lib_cache_mesh(struct zink_screen *screen, struct zink_gfx_program *prog)
|
||||||
|
{
|
||||||
|
unsigned idx = !!prog->shaders[MESA_SHADER_TASK];
|
||||||
|
struct set *ht = &screen->mesh_pipeline_libs[idx];
|
||||||
|
const uint32_t hash = prog->gfx_hash;
|
||||||
|
|
||||||
|
simple_mtx_lock(&screen->mesh_pipeline_libs_lock[idx]);
|
||||||
|
bool found = false;
|
||||||
|
struct set_entry *entry = _mesa_set_search_or_add_pre_hashed(ht, hash, prog->shaders, &found);
|
||||||
|
struct zink_gfx_lib_cache *libs;
|
||||||
|
if (found) {
|
||||||
|
libs = (void*)entry->key;
|
||||||
|
} else {
|
||||||
|
libs = create_lib_cache_mesh(prog);
|
||||||
|
memcpy(libs->shaders, prog->shaders, sizeof(prog->shaders));
|
||||||
|
entry->key = libs;
|
||||||
|
unsigned refs = 0;
|
||||||
|
for (unsigned i = MESA_SHADER_FRAGMENT; i < MESA_SHADER_MESH_STAGES; i++) {
|
||||||
|
if (prog->shaders[i]) {
|
||||||
|
simple_mtx_lock(&prog->shaders[i]->lock);
|
||||||
|
util_dynarray_append(&prog->shaders[i]->pipeline_libs, struct zink_gfx_lib_cache*, libs);
|
||||||
|
simple_mtx_unlock(&prog->shaders[i]->lock);
|
||||||
|
refs++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p_atomic_set(&libs->refcount, refs);
|
||||||
|
}
|
||||||
|
simple_mtx_unlock(&screen->mesh_pipeline_libs_lock[idx]);
|
||||||
|
return libs;
|
||||||
|
}
|
||||||
|
|
||||||
static struct zink_gfx_program *
|
static struct zink_gfx_program *
|
||||||
gfx_program_create(struct zink_context *ctx,
|
gfx_program_create(struct zink_context *ctx,
|
||||||
struct zink_shader **stages,
|
struct zink_shader **stages,
|
||||||
unsigned vertices_per_patch,
|
unsigned vertices_per_patch,
|
||||||
uint32_t gfx_hash)
|
uint32_t gfx_hash,
|
||||||
|
bool is_mesh)
|
||||||
{
|
{
|
||||||
struct zink_screen *screen = zink_screen(ctx->base.screen);
|
struct zink_screen *screen = zink_screen(ctx->base.screen);
|
||||||
struct zink_gfx_program *prog = create_program(ctx, false);
|
struct zink_gfx_program *prog = create_program(ctx, false);
|
||||||
|
|
@ -1111,14 +1290,14 @@ gfx_program_create(struct zink_context *ctx,
|
||||||
prog->base.removed = true;
|
prog->base.removed = true;
|
||||||
prog->optimal_keys = screen->optimal_keys;
|
prog->optimal_keys = screen->optimal_keys;
|
||||||
|
|
||||||
for (int i = 0; i < ZINK_GFX_SHADER_COUNT; ++i) {
|
for (int i = is_mesh ? MESA_SHADER_FRAGMENT : 0; i < (is_mesh ? MESA_SHADER_MESH_STAGES : MESA_SHADER_STAGES); ++i) {
|
||||||
util_dynarray_init(&prog->shader_cache[i][0][0], prog->base.ralloc_ctx);
|
util_dynarray_init(&prog->shader_cache[i][0][0], prog->base.ralloc_ctx);
|
||||||
util_dynarray_init(&prog->shader_cache[i][0][1], prog->base.ralloc_ctx);
|
util_dynarray_init(&prog->shader_cache[i][0][1], prog->base.ralloc_ctx);
|
||||||
util_dynarray_init(&prog->shader_cache[i][1][0], prog->base.ralloc_ctx);
|
util_dynarray_init(&prog->shader_cache[i][1][0], prog->base.ralloc_ctx);
|
||||||
util_dynarray_init(&prog->shader_cache[i][1][1], prog->base.ralloc_ctx);
|
util_dynarray_init(&prog->shader_cache[i][1][1], prog->base.ralloc_ctx);
|
||||||
if (stages[i]) {
|
if (stages[i]) {
|
||||||
prog->shaders[i] = stages[i];
|
prog->shaders[i] = stages[i];
|
||||||
prog->stages_present |= BITFIELD_BIT(i);
|
prog->stages_present |= BITFIELD_BIT(stages[i]->info.stage);
|
||||||
if (i != MESA_SHADER_FRAGMENT)
|
if (i != MESA_SHADER_FRAGMENT)
|
||||||
prog->optimal_keys &= !prog->shaders[i]->non_fs.is_generated;
|
prog->optimal_keys &= !prog->shaders[i]->non_fs.is_generated;
|
||||||
prog->needs_inlining |= prog->shaders[i]->needs_inlining;
|
prog->needs_inlining |= prog->shaders[i]->needs_inlining;
|
||||||
|
|
@ -1132,7 +1311,7 @@ gfx_program_create(struct zink_context *ctx,
|
||||||
prog->stages_present |= BITFIELD_BIT(MESA_SHADER_TESS_CTRL);
|
prog->stages_present |= BITFIELD_BIT(MESA_SHADER_TESS_CTRL);
|
||||||
}
|
}
|
||||||
prog->stages_remaining = prog->stages_present;
|
prog->stages_remaining = prog->stages_present;
|
||||||
for (int i = 0; i < ZINK_GFX_SHADER_COUNT; ++i) {
|
for (int i = 0; i < MESA_SHADER_MESH_STAGES; ++i) {
|
||||||
if (prog->shaders[i]) {
|
if (prog->shaders[i]) {
|
||||||
simple_mtx_lock(&prog->shaders[i]->lock);
|
simple_mtx_lock(&prog->shaders[i]->lock);
|
||||||
_mesa_set_add(prog->shaders[i]->programs, prog);
|
_mesa_set_add(prog->shaders[i]->programs, prog);
|
||||||
|
|
@ -1142,7 +1321,9 @@ gfx_program_create(struct zink_context *ctx,
|
||||||
}
|
}
|
||||||
p_atomic_dec(&prog->base.reference.count);
|
p_atomic_dec(&prog->base.reference.count);
|
||||||
|
|
||||||
if (stages[MESA_SHADER_GEOMETRY])
|
if (is_mesh)
|
||||||
|
prog->last_vertex_stage = stages[MESA_SHADER_MESH];
|
||||||
|
else if (stages[MESA_SHADER_GEOMETRY])
|
||||||
prog->last_vertex_stage = stages[MESA_SHADER_GEOMETRY];
|
prog->last_vertex_stage = stages[MESA_SHADER_GEOMETRY];
|
||||||
else if (stages[MESA_SHADER_TESS_EVAL])
|
else if (stages[MESA_SHADER_TESS_EVAL])
|
||||||
prog->last_vertex_stage = stages[MESA_SHADER_TESS_EVAL];
|
prog->last_vertex_stage = stages[MESA_SHADER_TESS_EVAL];
|
||||||
|
|
@ -1167,14 +1348,15 @@ static struct zink_gfx_program *
|
||||||
gfx_program_init(struct zink_context *ctx, struct zink_gfx_program *prog)
|
gfx_program_init(struct zink_context *ctx, struct zink_gfx_program *prog)
|
||||||
{
|
{
|
||||||
struct zink_screen *screen = zink_screen(ctx->base.screen);
|
struct zink_screen *screen = zink_screen(ctx->base.screen);
|
||||||
nir_shader *nir[ZINK_GFX_SHADER_COUNT];
|
nir_shader *nir[MESA_SHADER_MESH_STAGES];
|
||||||
|
bool is_mesh = !!prog->shaders[MESA_SHADER_MESH];
|
||||||
|
|
||||||
/* iterate in reverse order to create TES before generated TCS */
|
/* iterate in reverse order to create TES before generated TCS */
|
||||||
for (int i = MESA_SHADER_FRAGMENT; i >= MESA_SHADER_VERTEX; i--) {
|
for (int i = MESA_SHADER_MESH; i >= MESA_SHADER_VERTEX; i--) {
|
||||||
if (prog->shaders[i]) {
|
if (prog->shaders[i]) {
|
||||||
util_queue_fence_wait(&prog->shaders[i]->precompile.fence);
|
util_queue_fence_wait(&prog->shaders[i]->precompile.fence);
|
||||||
/* this may have already been precompiled for separate shader */
|
/* this may have already been precompiled for separate shader */
|
||||||
if (i == MESA_SHADER_TESS_CTRL && prog->shaders[i]->non_fs.is_generated && prog->shaders[MESA_SHADER_TESS_CTRL]->nir)
|
if (prog->shaders[i]->info.stage == MESA_SHADER_TESS_CTRL && prog->shaders[i]->non_fs.is_generated && prog->shaders[MESA_SHADER_TESS_CTRL]->nir)
|
||||||
zink_shader_tcs_init(screen, prog->shaders[MESA_SHADER_TESS_CTRL], nir[MESA_SHADER_TESS_EVAL], &nir[i]);
|
zink_shader_tcs_init(screen, prog->shaders[MESA_SHADER_TESS_CTRL], nir[MESA_SHADER_TESS_EVAL], &nir[i]);
|
||||||
else
|
else
|
||||||
nir[i] = zink_shader_deserialize(screen, prog->shaders[i]);
|
nir[i] = zink_shader_deserialize(screen, prog->shaders[i]);
|
||||||
|
|
@ -1182,21 +1364,29 @@ gfx_program_init(struct zink_context *ctx, struct zink_gfx_program *prog)
|
||||||
nir[i] = NULL;
|
nir[i] = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assign_io(screen, nir);
|
|
||||||
for (unsigned i = 0; i < ZINK_GFX_SHADER_COUNT; i++) {
|
if (is_mesh)
|
||||||
|
assign_io_mesh(screen, nir);
|
||||||
|
else
|
||||||
|
assign_io(screen, nir);
|
||||||
|
for (unsigned i = 0; i < MESA_SHADER_MESH_STAGES; i++) {
|
||||||
if (nir[i])
|
if (nir[i])
|
||||||
zink_shader_serialize_blob(nir[i], &prog->blobs[i]);
|
zink_shader_serialize_blob(nir[i], &prog->blobs[i]);
|
||||||
ralloc_free(nir[i]);
|
ralloc_free(nir[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (screen->optimal_keys)
|
if (screen->optimal_keys) {
|
||||||
prog->libs = find_or_create_lib_cache(screen, prog);
|
if (is_mesh)
|
||||||
|
prog->libs = find_or_create_lib_cache_mesh(screen, prog);
|
||||||
|
else
|
||||||
|
prog->libs = find_or_create_lib_cache(screen, prog);
|
||||||
|
}
|
||||||
if (prog->libs)
|
if (prog->libs)
|
||||||
p_atomic_inc(&prog->libs->refcount);
|
p_atomic_inc(&prog->libs->refcount);
|
||||||
|
|
||||||
struct mesa_blake3 sctx;
|
struct mesa_blake3 sctx;
|
||||||
_mesa_blake3_init(&sctx);
|
_mesa_blake3_init(&sctx);
|
||||||
for (int i = 0; i < ZINK_GFX_SHADER_COUNT; ++i) {
|
for (int i = 0; i < MESA_SHADER_MESH_STAGES; ++i) {
|
||||||
if (prog->shaders[i])
|
if (prog->shaders[i])
|
||||||
_mesa_blake3_update(&sctx, prog->shaders[i]->base.sha1, sizeof(prog->shaders[i]->base.sha1));
|
_mesa_blake3_update(&sctx, prog->shaders[i]->base.sha1, sizeof(prog->shaders[i]->base.sha1));
|
||||||
}
|
}
|
||||||
|
|
@ -1217,9 +1407,10 @@ struct zink_gfx_program *
|
||||||
zink_create_gfx_program(struct zink_context *ctx,
|
zink_create_gfx_program(struct zink_context *ctx,
|
||||||
struct zink_shader **stages,
|
struct zink_shader **stages,
|
||||||
unsigned vertices_per_patch,
|
unsigned vertices_per_patch,
|
||||||
uint32_t gfx_hash)
|
uint32_t gfx_hash,
|
||||||
|
bool is_mesh)
|
||||||
{
|
{
|
||||||
struct zink_gfx_program *prog = gfx_program_create(ctx, stages, vertices_per_patch, gfx_hash);
|
struct zink_gfx_program *prog = gfx_program_create(ctx, stages, vertices_per_patch, gfx_hash, is_mesh);
|
||||||
if (prog)
|
if (prog)
|
||||||
prog = gfx_program_init(ctx, prog);
|
prog = gfx_program_init(ctx, prog);
|
||||||
return prog;
|
return prog;
|
||||||
|
|
@ -1235,7 +1426,7 @@ create_linked_separable_job(void *data, void *gdata, int thread_index)
|
||||||
/* this is a dead program */
|
/* this is a dead program */
|
||||||
if (prog->base.removed)
|
if (prog->base.removed)
|
||||||
return;
|
return;
|
||||||
prog->full_prog = gfx_program_create(prog->base.ctx, prog->shaders, 0, prog->gfx_hash);
|
prog->full_prog = gfx_program_create(prog->base.ctx, prog->shaders, 0, prog->gfx_hash, !!prog->shaders[MESA_SHADER_MESH]);
|
||||||
/* block gfx_shader_prune in the main thread */
|
/* block gfx_shader_prune in the main thread */
|
||||||
util_queue_fence_reset(&prog->full_prog->base.cache_fence);
|
util_queue_fence_reset(&prog->full_prog->base.cache_fence);
|
||||||
/* add an ownership ref */
|
/* add an ownership ref */
|
||||||
|
|
@ -1247,24 +1438,28 @@ create_linked_separable_job(void *data, void *gdata, int thread_index)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct zink_gfx_program *
|
struct zink_gfx_program *
|
||||||
create_gfx_program_separable(struct zink_context *ctx, struct zink_shader **stages, unsigned vertices_per_patch)
|
create_gfx_program_separable(struct zink_context *ctx, struct zink_shader **stages, unsigned vertices_per_patch, bool is_mesh)
|
||||||
{
|
{
|
||||||
struct zink_screen *screen = zink_screen(ctx->base.screen);
|
struct zink_screen *screen = zink_screen(ctx->base.screen);
|
||||||
bool is_separate = true;
|
bool is_separate = true;
|
||||||
for (unsigned i = 0; i < ZINK_GFX_SHADER_COUNT; i++)
|
for (unsigned i = 0; i < MESA_SHADER_MESH_STAGES; i++)
|
||||||
is_separate &= !stages[i] || stages[i]->info.separate_shader;
|
is_separate &= !stages[i] || stages[i]->info.separate_shader;
|
||||||
/* filter cases that need real pipelines */
|
/* filter cases that need real pipelines */
|
||||||
|
bool is_default = is_mesh ? ZINK_SHADER_KEY_OPTIMAL_IS_DEFAULT_MESH(ctx->gfx_pipeline_state.optimal_key) :
|
||||||
|
ZINK_SHADER_KEY_OPTIMAL_IS_DEFAULT(ctx->gfx_pipeline_state.optimal_key);
|
||||||
|
bool can_gpl = is_mesh ? zink_can_use_pipeline_libs_mesh(ctx) : zink_can_use_pipeline_libs(ctx);
|
||||||
|
uint32_t hash = is_mesh ? ctx->mesh_hash : ctx->gfx_hash;
|
||||||
if (!is_separate ||
|
if (!is_separate ||
|
||||||
/* TODO: maybe try variants? grimace */
|
/* TODO: maybe try variants? grimace */
|
||||||
!ZINK_SHADER_KEY_OPTIMAL_IS_DEFAULT(ctx->gfx_pipeline_state.optimal_key) ||
|
!is_default ||
|
||||||
!zink_can_use_pipeline_libs(ctx))
|
!can_gpl)
|
||||||
return zink_create_gfx_program(ctx, stages, vertices_per_patch, ctx->gfx_hash);
|
return zink_create_gfx_program(ctx, stages, vertices_per_patch, hash, is_mesh);
|
||||||
for (unsigned i = 0; i < ZINK_GFX_SHADER_COUNT; i++) {
|
for (unsigned i = 0; i < MESA_SHADER_MESH_STAGES; i++) {
|
||||||
/* ensure async shader creation is done */
|
/* ensure async shader creation is done */
|
||||||
if (stages[i]) {
|
if (stages[i]) {
|
||||||
util_queue_fence_wait(&stages[i]->precompile.fence);
|
util_queue_fence_wait(&stages[i]->precompile.fence);
|
||||||
if (!stages[i]->precompile.obj.mod)
|
if (!stages[i]->precompile.obj.mod)
|
||||||
return zink_create_gfx_program(ctx, stages, vertices_per_patch, ctx->gfx_hash);
|
return zink_create_gfx_program(ctx, stages, vertices_per_patch, hash, is_mesh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1273,8 +1468,10 @@ create_gfx_program_separable(struct zink_context *ctx, struct zink_shader **stag
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
prog->is_separable = true;
|
prog->is_separable = true;
|
||||||
prog->gfx_hash = ctx->gfx_hash;
|
prog->gfx_hash = hash;
|
||||||
prog->base.uses_shobj = screen->info.have_EXT_shader_object && !stages[MESA_SHADER_VERTEX]->info.view_mask && !BITSET_TEST(stages[MESA_SHADER_FRAGMENT]->info.system_values_read, SYSTEM_VALUE_SAMPLE_MASK_IN);
|
prog->base.uses_shobj = screen->info.have_EXT_shader_object &&
|
||||||
|
(is_mesh || !stages[MESA_SHADER_VERTEX]->info.view_mask) &&
|
||||||
|
!BITSET_TEST(stages[MESA_SHADER_FRAGMENT]->info.system_values_read, SYSTEM_VALUE_SAMPLE_MASK_IN);
|
||||||
|
|
||||||
prog->stages_remaining = prog->stages_present = ctx->shader_stages;
|
prog->stages_remaining = prog->stages_present = ctx->shader_stages;
|
||||||
memcpy(prog->shaders, stages, sizeof(prog->shaders));
|
memcpy(prog->shaders, stages, sizeof(prog->shaders));
|
||||||
|
|
@ -1292,7 +1489,7 @@ create_gfx_program_separable(struct zink_context *ctx, struct zink_shader **stag
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned refs = 0;
|
unsigned refs = 0;
|
||||||
for (int i = 0; i < ZINK_GFX_SHADER_COUNT; ++i) {
|
for (int i = 0; i < MESA_SHADER_MESH_STAGES; ++i) {
|
||||||
if (prog->shaders[i]) {
|
if (prog->shaders[i]) {
|
||||||
simple_mtx_lock(&prog->shaders[i]->lock);
|
simple_mtx_lock(&prog->shaders[i]->lock);
|
||||||
_mesa_set_add(prog->shaders[i]->programs, prog);
|
_mesa_set_add(prog->shaders[i]->programs, prog);
|
||||||
|
|
@ -1313,7 +1510,7 @@ create_gfx_program_separable(struct zink_context *ctx, struct zink_shader **stag
|
||||||
_mesa_hash_table_init(&prog->pipelines[i], prog->base.ralloc_ctx, NULL, zink_get_gfx_pipeline_eq_func(screen, prog));
|
_mesa_hash_table_init(&prog->pipelines[i], prog->base.ralloc_ctx, NULL, zink_get_gfx_pipeline_eq_func(screen, prog));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < ZINK_GFX_SHADER_COUNT; ++i) {
|
for (int i = 0; i < MESA_SHADER_MESH_STAGES; ++i) {
|
||||||
if (!prog->shaders[i] || !prog->shaders[i]->precompile.dsl)
|
if (!prog->shaders[i] || !prog->shaders[i]->precompile.dsl)
|
||||||
continue;
|
continue;
|
||||||
int idx = !i ? 0 : screen->info.have_EXT_shader_object ? i : 1;
|
int idx = !i ? 0 : screen->info.have_EXT_shader_object ? i : 1;
|
||||||
|
|
@ -1330,7 +1527,7 @@ create_gfx_program_separable(struct zink_context *ctx, struct zink_shader **stag
|
||||||
}
|
}
|
||||||
prog->base.layout = zink_pipeline_layout_create(screen, prog->base.dsl, prog->base.num_dsl, false, VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT);
|
prog->base.layout = zink_pipeline_layout_create(screen, prog->base.dsl, prog->base.num_dsl, false, VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT);
|
||||||
|
|
||||||
prog->last_variant_hash = ctx->gfx_pipeline_state.optimal_key;
|
prog->last_variant_hash = is_mesh ? ctx->gfx_pipeline_state.mesh_optimal_key : ctx->gfx_pipeline_state.optimal_key;
|
||||||
|
|
||||||
if (!screen->info.have_EXT_shader_object) {
|
if (!screen->info.have_EXT_shader_object) {
|
||||||
VkPipeline libs[] = {stages[MESA_SHADER_VERTEX]->precompile.gpl, stages[MESA_SHADER_FRAGMENT]->precompile.gpl};
|
VkPipeline libs[] = {stages[MESA_SHADER_VERTEX]->precompile.gpl, stages[MESA_SHADER_FRAGMENT]->precompile.gpl};
|
||||||
|
|
@ -1608,7 +1805,7 @@ zink_program_num_bindings_typed(const struct zink_program *pg, enum zink_descrip
|
||||||
return get_num_bindings(comp->shader, type);
|
return get_num_bindings(comp->shader, type);
|
||||||
}
|
}
|
||||||
struct zink_gfx_program *prog = (void*)pg;
|
struct zink_gfx_program *prog = (void*)pg;
|
||||||
for (unsigned i = 0; i < ZINK_GFX_SHADER_COUNT; i++) {
|
for (unsigned i = 0; i < MESA_SHADER_MESH_STAGES; i++) {
|
||||||
if (prog->shaders[i])
|
if (prog->shaders[i])
|
||||||
num_bindings += get_num_bindings(prog->shaders[i], type);
|
num_bindings += get_num_bindings(prog->shaders[i], type);
|
||||||
}
|
}
|
||||||
|
|
@ -1656,7 +1853,7 @@ zink_destroy_gfx_program(struct zink_screen *screen,
|
||||||
|
|
||||||
deinit_program(screen, &prog->base);
|
deinit_program(screen, &prog->base);
|
||||||
|
|
||||||
for (int i = 0; i < ZINK_GFX_SHADER_COUNT; ++i) {
|
for (int i = 0; i < MESA_SHADER_MESH_STAGES; ++i) {
|
||||||
if (prog->shaders[i]) {
|
if (prog->shaders[i]) {
|
||||||
_mesa_set_remove_key(prog->shaders[i]->programs, prog);
|
_mesa_set_remove_key(prog->shaders[i]->programs, prog);
|
||||||
prog->shaders[i] = NULL;
|
prog->shaders[i] = NULL;
|
||||||
|
|
@ -1789,8 +1986,12 @@ bind_gfx_stage(struct zink_context *ctx, mesa_shader_stage stage, struct zink_sh
|
||||||
else
|
else
|
||||||
ctx->shader_has_inlinable_uniforms_mask &= ~(1 << stage);
|
ctx->shader_has_inlinable_uniforms_mask &= ~(1 << stage);
|
||||||
|
|
||||||
if (ctx->gfx_stages[stage])
|
if (ctx->gfx_stages[stage]) {
|
||||||
ctx->gfx_hash ^= ctx->gfx_stages[stage]->hash;
|
if (stage < MESA_SHADER_COMPUTE)
|
||||||
|
ctx->gfx_hash ^= ctx->gfx_stages[stage]->hash;
|
||||||
|
if (stage == MESA_SHADER_FRAGMENT || stage > MESA_SHADER_COMPUTE)
|
||||||
|
ctx->mesh_hash ^= ctx->gfx_stages[stage]->hash;
|
||||||
|
}
|
||||||
|
|
||||||
if (stage == MESA_SHADER_GEOMETRY && ctx->is_generated_gs_bound && (!shader || !shader->non_fs.parent)) {
|
if (stage == MESA_SHADER_GEOMETRY && ctx->is_generated_gs_bound && (!shader || !shader->non_fs.parent)) {
|
||||||
ctx->inlinable_uniforms_valid_mask &= ~BITFIELD64_BIT(MESA_SHADER_GEOMETRY);
|
ctx->inlinable_uniforms_valid_mask &= ~BITFIELD64_BIT(MESA_SHADER_GEOMETRY);
|
||||||
|
|
@ -1798,17 +1999,33 @@ bind_gfx_stage(struct zink_context *ctx, mesa_shader_stage stage, struct zink_sh
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->gfx_stages[stage] = shader;
|
ctx->gfx_stages[stage] = shader;
|
||||||
ctx->gfx_dirty = ctx->gfx_stages[MESA_SHADER_FRAGMENT] && ctx->gfx_stages[MESA_SHADER_VERTEX];
|
if (stage < MESA_SHADER_COMPUTE)
|
||||||
ctx->gfx_pipeline_state.modules_changed = true;
|
ctx->gfx_dirty = ctx->gfx_stages[MESA_SHADER_FRAGMENT] && ctx->gfx_stages[MESA_SHADER_VERTEX];
|
||||||
|
if (stage == MESA_SHADER_FRAGMENT || stage > MESA_SHADER_COMPUTE)
|
||||||
|
ctx->mesh_dirty = ctx->gfx_stages[MESA_SHADER_FRAGMENT] && ctx->gfx_stages[MESA_SHADER_MESH];
|
||||||
|
if (stage <= MESA_SHADER_FRAGMENT)
|
||||||
|
ctx->gfx_pipeline_state.modules_changed = true;
|
||||||
|
if (stage >= MESA_SHADER_FRAGMENT)
|
||||||
|
ctx->gfx_pipeline_state.mesh_modules_changed = true;
|
||||||
if (shader) {
|
if (shader) {
|
||||||
ctx->shader_stages |= BITFIELD_BIT(stage);
|
ctx->shader_stages |= BITFIELD_BIT(stage);
|
||||||
ctx->gfx_hash ^= ctx->gfx_stages[stage]->hash;
|
if (stage < MESA_SHADER_COMPUTE)
|
||||||
|
ctx->gfx_hash ^= ctx->gfx_stages[stage]->hash;
|
||||||
|
if (stage == MESA_SHADER_FRAGMENT || stage > MESA_SHADER_COMPUTE)
|
||||||
|
ctx->mesh_hash ^= ctx->gfx_stages[stage]->hash;
|
||||||
if (shader->info.uses_bindless)
|
if (shader->info.uses_bindless)
|
||||||
zink_descriptors_init_bindless(ctx);
|
zink_descriptors_init_bindless(ctx);
|
||||||
} else {
|
} else {
|
||||||
if (ctx->curr_program)
|
if (stage < MESA_SHADER_COMPUTE) {
|
||||||
ctx->gfx_pipeline_state.final_hash ^= ctx->curr_program->last_variant_hash;
|
if (ctx->curr_program)
|
||||||
ctx->curr_program = NULL;
|
ctx->gfx_pipeline_state.final_hash ^= ctx->curr_program->last_variant_hash;
|
||||||
|
ctx->curr_program = NULL;
|
||||||
|
}
|
||||||
|
if (stage == MESA_SHADER_FRAGMENT || stage > MESA_SHADER_COMPUTE) {
|
||||||
|
if (ctx->mesh_program)
|
||||||
|
ctx->gfx_pipeline_state.mesh_final_hash ^= ctx->mesh_program->last_variant_hash;
|
||||||
|
ctx->mesh_program = NULL;
|
||||||
|
}
|
||||||
ctx->shader_stages &= ~BITFIELD_BIT(stage);
|
ctx->shader_stages &= ~BITFIELD_BIT(stage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2005,7 +2222,7 @@ zink_bind_fs_state(struct pipe_context *pctx,
|
||||||
zink_update_fs_key_samples(ctx);
|
zink_update_fs_key_samples(ctx);
|
||||||
if (zink_screen(pctx->screen)->info.have_EXT_rasterization_order_attachment_access) {
|
if (zink_screen(pctx->screen)->info.have_EXT_rasterization_order_attachment_access) {
|
||||||
if (ctx->gfx_pipeline_state.rast_attachment_order != info->fs.uses_fbfetch_output)
|
if (ctx->gfx_pipeline_state.rast_attachment_order != info->fs.uses_fbfetch_output)
|
||||||
ctx->gfx_pipeline_state.dirty = true;
|
ctx->gfx_pipeline_state.dirty = ctx->gfx_pipeline_state.mesh_dirty = true;
|
||||||
ctx->gfx_pipeline_state.rast_attachment_order = info->fs.uses_fbfetch_output;
|
ctx->gfx_pipeline_state.rast_attachment_order = info->fs.uses_fbfetch_output;
|
||||||
}
|
}
|
||||||
zink_set_zs_needs_shader_swizzle_key(ctx, MESA_SHADER_FRAGMENT, false);
|
zink_set_zs_needs_shader_swizzle_key(ctx, MESA_SHADER_FRAGMENT, false);
|
||||||
|
|
@ -2018,6 +2235,34 @@ zink_bind_fs_state(struct pipe_context *pctx,
|
||||||
zink_update_fbfetch(ctx);
|
zink_update_fbfetch(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
zink_bind_ts_state(struct pipe_context *pctx,
|
||||||
|
void *cso)
|
||||||
|
{
|
||||||
|
struct zink_context *ctx = zink_context(pctx);
|
||||||
|
if (!cso && !ctx->gfx_stages[MESA_SHADER_TASK])
|
||||||
|
return;
|
||||||
|
bind_gfx_stage(ctx, MESA_SHADER_TASK, cso);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
zink_bind_ms_state(struct pipe_context *pctx,
|
||||||
|
void *cso)
|
||||||
|
{
|
||||||
|
struct zink_context *ctx = zink_context(pctx);
|
||||||
|
if (!cso && !ctx->gfx_stages[MESA_SHADER_MESH])
|
||||||
|
return;
|
||||||
|
bind_gfx_stage(ctx, MESA_SHADER_MESH, cso);
|
||||||
|
|
||||||
|
if (!cso)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ctx->gfx_stages[MESA_SHADER_MESH]->info.outputs_written & (VARYING_BIT_VIEWPORT | VARYING_BIT_VIEWPORT_MASK))
|
||||||
|
ctx->vp_state.mesh_num_viewports = MIN2(zink_screen(pctx->screen)->info.props.limits.maxViewports, PIPE_MAX_VIEWPORTS);
|
||||||
|
else
|
||||||
|
ctx->vp_state.mesh_num_viewports = 1;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
zink_bind_gs_state(struct pipe_context *pctx,
|
zink_bind_gs_state(struct pipe_context *pctx,
|
||||||
void *cso)
|
void *cso)
|
||||||
|
|
@ -2120,14 +2365,15 @@ struct zink_gfx_library_key *
|
||||||
zink_create_pipeline_lib(struct zink_screen *screen, struct zink_gfx_program *prog, struct zink_gfx_pipeline_state *state)
|
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 = CALLOC_STRUCT(zink_gfx_library_key);
|
struct zink_gfx_library_key *gkey = CALLOC_STRUCT(zink_gfx_library_key);
|
||||||
|
bool is_mesh = !prog->shaders[MESA_SHADER_VERTEX];
|
||||||
if (!gkey) {
|
if (!gkey) {
|
||||||
mesa_loge("ZINK: failed to allocate gkey!");
|
mesa_loge("ZINK: failed to allocate gkey!");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
gkey->optimal_key = state->optimal_key;
|
gkey->optimal_key = !is_mesh ? state->optimal_key : state->mesh_optimal_key;
|
||||||
assert(gkey->optimal_key);
|
assert(is_mesh || gkey->optimal_key);
|
||||||
for (unsigned i = 0; i < ZINK_GFX_SHADER_COUNT; i++)
|
for (unsigned i = 0; i < MESA_SHADER_MESH_STAGES; i++)
|
||||||
gkey->modules[i] = prog->objs[i].mod;
|
gkey->modules[i] = prog->objs[i].mod;
|
||||||
gkey->pipeline = zink_create_gfx_pipeline_library(screen, prog);
|
gkey->pipeline = zink_create_gfx_pipeline_library(screen, prog);
|
||||||
_mesa_set_add(&prog->libs->libs, gkey);
|
_mesa_set_add(&prog->libs->libs, gkey);
|
||||||
|
|
@ -2193,13 +2439,13 @@ zink_link_gfx_shader(struct pipe_context *pctx, void **shaders)
|
||||||
if (zshaders[MESA_SHADER_FRAGMENT] && zshaders[MESA_SHADER_FRAGMENT]->info.fs.uses_sample_shading)
|
if (zshaders[MESA_SHADER_FRAGMENT] && zshaders[MESA_SHADER_FRAGMENT]->info.fs.uses_sample_shading)
|
||||||
return;
|
return;
|
||||||
/* can't precompile fixedfunc */
|
/* can't precompile fixedfunc */
|
||||||
if (!shaders[MESA_SHADER_VERTEX] || !shaders[MESA_SHADER_FRAGMENT]) {
|
if ((!shaders[MESA_SHADER_VERTEX] && !shaders[MESA_SHADER_MESH]) || !shaders[MESA_SHADER_FRAGMENT]) {
|
||||||
/* handled directly from shader create */
|
/* handled directly from shader create */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
unsigned hash = 0;
|
unsigned hash = 0;
|
||||||
unsigned shader_stages = 0;
|
unsigned shader_stages = 0;
|
||||||
for (unsigned i = 0; i < ZINK_GFX_SHADER_COUNT; i++) {
|
for (unsigned i = 0; i < MESA_SHADER_MESH_STAGES; i++) {
|
||||||
if (zshaders[i]) {
|
if (zshaders[i]) {
|
||||||
hash ^= zshaders[i]->hash;
|
hash ^= zshaders[i]->hash;
|
||||||
shader_stages |= BITFIELD_BIT(i);
|
shader_stages |= BITFIELD_BIT(i);
|
||||||
|
|
@ -2210,19 +2456,21 @@ zink_link_gfx_shader(struct pipe_context *pctx, void **shaders)
|
||||||
/* can't do fixedfunc tes either */
|
/* can't do fixedfunc tes either */
|
||||||
if (tess && !shaders[MESA_SHADER_TESS_EVAL])
|
if (tess && !shaders[MESA_SHADER_TESS_EVAL])
|
||||||
return;
|
return;
|
||||||
struct hash_table *ht = &ctx->program_cache[zink_program_cache_stages(shader_stages)];
|
bool is_mesh = (shader_stages & BITFIELD_BIT(MESA_SHADER_MESH)) > 0;
|
||||||
simple_mtx_lock(&ctx->program_lock[zink_program_cache_stages(shader_stages)]);
|
struct hash_table *ht = is_mesh ? &ctx->mesh_cache[zink_mesh_cache_stages(shader_stages)] : &ctx->program_cache[zink_program_cache_stages(shader_stages)];
|
||||||
|
simple_mtx_t *lock = is_mesh ? &ctx->mesh_lock[zink_mesh_cache_stages(shader_stages)] : &ctx->program_lock[zink_program_cache_stages(shader_stages)];
|
||||||
|
simple_mtx_lock(lock);
|
||||||
/* link can be called repeatedly with the same shaders: ignore */
|
/* link can be called repeatedly with the same shaders: ignore */
|
||||||
if (_mesa_hash_table_search_pre_hashed(ht, hash, shaders)) {
|
if (_mesa_hash_table_search_pre_hashed(ht, hash, shaders)) {
|
||||||
simple_mtx_unlock(&ctx->program_lock[zink_program_cache_stages(shader_stages)]);
|
simple_mtx_unlock(lock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
struct zink_gfx_program *prog = gfx_program_create(ctx, zshaders, 3, hash);
|
struct zink_gfx_program *prog = gfx_program_create(ctx, zshaders, 3, hash, is_mesh);
|
||||||
u_foreach_bit(i, shader_stages)
|
u_foreach_bit(i, shader_stages)
|
||||||
assert(prog->shaders[i]);
|
assert(prog->shaders[i]);
|
||||||
_mesa_hash_table_insert_pre_hashed(ht, hash, prog->shaders, prog);
|
_mesa_hash_table_insert_pre_hashed(ht, hash, prog->shaders, prog);
|
||||||
prog->base.removed = false;
|
prog->base.removed = false;
|
||||||
simple_mtx_unlock(&ctx->program_lock[zink_program_cache_stages(shader_stages)]);
|
simple_mtx_unlock(lock);
|
||||||
if (zink_debug & ZINK_DEBUG_SHADERDB) {
|
if (zink_debug & ZINK_DEBUG_SHADERDB) {
|
||||||
struct zink_screen *screen = zink_screen(pctx->screen);
|
struct zink_screen *screen = zink_screen(pctx->screen);
|
||||||
gfx_program_init(ctx, prog);
|
gfx_program_init(ctx, prog);
|
||||||
|
|
@ -2237,7 +2485,8 @@ zink_link_gfx_shader(struct pipe_context *pctx, void **shaders)
|
||||||
VKSCR(DestroyPipeline)(screen->dev, pipeline, NULL);
|
VKSCR(DestroyPipeline)(screen->dev, pipeline, NULL);
|
||||||
} else {
|
} else {
|
||||||
if (zink_screen(pctx->screen)->info.have_EXT_shader_object)
|
if (zink_screen(pctx->screen)->info.have_EXT_shader_object)
|
||||||
prog->base.uses_shobj = !zshaders[MESA_SHADER_VERTEX]->info.view_mask && !BITSET_TEST(zshaders[MESA_SHADER_FRAGMENT]->info.system_values_read, SYSTEM_VALUE_SAMPLE_MASK_IN);
|
prog->base.uses_shobj = (!zshaders[MESA_SHADER_VERTEX] || !zshaders[MESA_SHADER_VERTEX]->info.view_mask) &&
|
||||||
|
!BITSET_TEST(zshaders[MESA_SHADER_FRAGMENT]->info.system_values_read, SYSTEM_VALUE_SAMPLE_MASK_IN);
|
||||||
if (zink_debug & ZINK_DEBUG_NOBGC) {
|
if (zink_debug & ZINK_DEBUG_NOBGC) {
|
||||||
gfx_program_precompile_job(prog, pctx->screen, 0);
|
gfx_program_precompile_job(prog, pctx->screen, 0);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -2258,7 +2507,7 @@ precompile_separate_shader(struct zink_shader *zs, struct zink_screen *screen)
|
||||||
{
|
{
|
||||||
zs->precompile.obj = zink_shader_compile_separate(screen, zs);
|
zs->precompile.obj = zink_shader_compile_separate(screen, zs);
|
||||||
if (!screen->info.have_EXT_shader_object) {
|
if (!screen->info.have_EXT_shader_object) {
|
||||||
struct zink_shader_object objs[ZINK_GFX_SHADER_COUNT] = {0};
|
struct zink_shader_object objs[MESA_SHADER_MESH_STAGES] = {0};
|
||||||
objs[zs->info.stage].mod = zs->precompile.obj.mod;
|
objs[zs->info.stage].mod = zs->precompile.obj.mod;
|
||||||
zs->precompile.gpl = zink_create_gfx_pipeline_separate(screen, objs, zs->precompile.layout, zs->info.stage);
|
zs->precompile.gpl = zink_create_gfx_pipeline_separate(screen, objs, zs->precompile.layout, zs->info.stage);
|
||||||
}
|
}
|
||||||
|
|
@ -2279,7 +2528,7 @@ gfx_shader_init_job(void *data, void *gdata, int thread_index)
|
||||||
}
|
}
|
||||||
if (zs->info.separate_shader && zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB &&
|
if (zs->info.separate_shader && zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB &&
|
||||||
(screen->info.have_EXT_shader_object ||
|
(screen->info.have_EXT_shader_object ||
|
||||||
(screen->info.have_EXT_graphics_pipeline_library && (zs->info.stage == MESA_SHADER_FRAGMENT || zs->info.stage == MESA_SHADER_VERTEX)))) {
|
(screen->info.have_EXT_graphics_pipeline_library && (zs->info.stage == MESA_SHADER_FRAGMENT || zs->info.stage == MESA_SHADER_VERTEX || zs->info.stage == MESA_SHADER_MESH)))) {
|
||||||
/* sample shading can't precompile */
|
/* sample shading can't precompile */
|
||||||
if (zs->info.stage != MESA_SHADER_FRAGMENT || !zs->info.fs.uses_sample_shading)
|
if (zs->info.stage != MESA_SHADER_FRAGMENT || !zs->info.fs.uses_sample_shading)
|
||||||
precompile_separate_shader(zs, screen);
|
precompile_separate_shader(zs, screen);
|
||||||
|
|
@ -2349,6 +2598,14 @@ zink_program_init(struct zink_context *ctx)
|
||||||
ctx->base.bind_tes_state = zink_bind_tes_state;
|
ctx->base.bind_tes_state = zink_bind_tes_state;
|
||||||
ctx->base.delete_tes_state = zink_delete_cached_shader_state;
|
ctx->base.delete_tes_state = zink_delete_cached_shader_state;
|
||||||
|
|
||||||
|
ctx->base.create_ts_state = zink_create_cached_shader_state;
|
||||||
|
ctx->base.bind_ts_state = zink_bind_ts_state;
|
||||||
|
ctx->base.delete_ts_state = zink_delete_cached_shader_state;
|
||||||
|
|
||||||
|
ctx->base.create_ms_state = zink_create_cached_shader_state;
|
||||||
|
ctx->base.bind_ms_state = zink_bind_ms_state;
|
||||||
|
ctx->base.delete_ms_state = zink_delete_cached_shader_state;
|
||||||
|
|
||||||
ctx->base.create_compute_state = zink_create_cs_state;
|
ctx->base.create_compute_state = zink_create_cs_state;
|
||||||
ctx->base.bind_compute_state = zink_bind_cs_state;
|
ctx->base.bind_compute_state = zink_bind_cs_state;
|
||||||
ctx->base.get_compute_state_info = zink_get_compute_state_info;
|
ctx->base.get_compute_state_info = zink_get_compute_state_info;
|
||||||
|
|
|
||||||
|
|
@ -123,6 +123,8 @@ void
|
||||||
zink_gfx_program_update(struct zink_context *ctx);
|
zink_gfx_program_update(struct zink_context *ctx);
|
||||||
void
|
void
|
||||||
zink_gfx_program_update_optimal(struct zink_context *ctx);
|
zink_gfx_program_update_optimal(struct zink_context *ctx);
|
||||||
|
void
|
||||||
|
zink_mesh_program_update_optimal(struct zink_context *ctx);
|
||||||
|
|
||||||
|
|
||||||
struct zink_gfx_library_key *
|
struct zink_gfx_library_key *
|
||||||
|
|
@ -156,7 +158,8 @@ struct zink_gfx_program *
|
||||||
zink_create_gfx_program(struct zink_context *ctx,
|
zink_create_gfx_program(struct zink_context *ctx,
|
||||||
struct zink_shader **stages,
|
struct zink_shader **stages,
|
||||||
unsigned vertices_per_patch,
|
unsigned vertices_per_patch,
|
||||||
uint32_t gfx_hash);
|
uint32_t gfx_hash,
|
||||||
|
bool is_mesh);
|
||||||
|
|
||||||
void
|
void
|
||||||
zink_destroy_gfx_program(struct zink_screen *screen,
|
zink_destroy_gfx_program(struct zink_screen *screen,
|
||||||
|
|
@ -432,6 +435,31 @@ zink_can_use_shader_objects(const struct zink_context *ctx)
|
||||||
!ctx->is_generated_gs_bound;
|
!ctx->is_generated_gs_bound;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE static bool
|
||||||
|
zink_can_use_pipeline_libs_mesh(const struct zink_context *ctx)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
/* this is just terrible */
|
||||||
|
!zink_get_fs_base_key(ctx)->shadow_needs_shader_swizzle &&
|
||||||
|
/* TODO: is sample shading even possible to handle with GPL? */
|
||||||
|
!ctx->gfx_stages[MESA_SHADER_FRAGMENT]->info.fs.uses_sample_shading &&
|
||||||
|
!zink_get_fs_base_key(ctx)->fbfetch_ms &&
|
||||||
|
!ctx->gfx_pipeline_state.force_persample_interp &&
|
||||||
|
!ctx->gfx_pipeline_state.min_samples;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* stricter requirements */
|
||||||
|
ALWAYS_INLINE static bool
|
||||||
|
zink_can_use_shader_objects_mesh(const struct zink_context *ctx)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
ZINK_SHADER_KEY_OPTIMAL_IS_DEFAULT_MESH(ctx->gfx_pipeline_state.optimal_key) &&
|
||||||
|
/* TODO: is sample shading even possible to handle with GPL? */
|
||||||
|
!ctx->gfx_stages[MESA_SHADER_FRAGMENT]->info.fs.uses_sample_shading &&
|
||||||
|
!ctx->gfx_pipeline_state.force_persample_interp &&
|
||||||
|
!ctx->gfx_pipeline_state.min_samples;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
zink_set_rasterizer_discard(struct zink_context *ctx, bool disable);
|
zink_set_rasterizer_discard(struct zink_context *ctx, bool disable);
|
||||||
void
|
void
|
||||||
|
|
@ -465,6 +493,18 @@ zink_sanitize_optimal_key(struct zink_shader **shaders, uint32_t val)
|
||||||
k.fs.force_dual_color_blend = false;
|
k.fs.force_dual_color_blend = false;
|
||||||
return k.val;
|
return k.val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline uint32_t
|
||||||
|
zink_sanitize_optimal_key_mesh(struct zink_shader **shaders, uint32_t val)
|
||||||
|
{
|
||||||
|
union zink_shader_key_optimal k;
|
||||||
|
k.val = zink_shader_key_optimal_mesh(val);
|
||||||
|
if (!zink_shader_uses_samples(shaders[MESA_SHADER_FRAGMENT]))
|
||||||
|
k.fs.samples = false;
|
||||||
|
if (!(shaders[MESA_SHADER_FRAGMENT]->info.outputs_written & BITFIELD64_BIT(FRAG_RESULT_DATA1)))
|
||||||
|
k.fs.force_dual_color_blend = false;
|
||||||
|
return k.val;
|
||||||
|
}
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,7 @@ check_vertex_strides(struct zink_context *ctx)
|
||||||
* in theory, zink supports many feature levels,
|
* in theory, zink supports many feature levels,
|
||||||
* but it's important to provide a more optimized codepath for drivers that support all the best features
|
* but it's important to provide a more optimized codepath for drivers that support all the best features
|
||||||
*/
|
*/
|
||||||
template <zink_dynamic_state DYNAMIC_STATE, bool HAVE_LIB>
|
template <zink_dynamic_state DYNAMIC_STATE, bool HAVE_LIB, bool IS_MESH>
|
||||||
VkPipeline
|
VkPipeline
|
||||||
zink_get_gfx_pipeline(struct zink_context *ctx,
|
zink_get_gfx_pipeline(struct zink_context *ctx,
|
||||||
struct zink_gfx_program *prog,
|
struct zink_gfx_program *prog,
|
||||||
|
|
@ -109,78 +109,114 @@ zink_get_gfx_pipeline(struct zink_context *ctx,
|
||||||
struct zink_screen *screen = zink_screen(ctx->base.screen);
|
struct zink_screen *screen = zink_screen(ctx->base.screen);
|
||||||
bool uses_dynamic_stride = state->uses_dynamic_stride;
|
bool uses_dynamic_stride = state->uses_dynamic_stride;
|
||||||
|
|
||||||
VkPrimitiveTopology vkmode = zink_primitive_topology(mode);
|
VkPrimitiveTopology vkmode = IS_MESH ? VK_PRIMITIVE_TOPOLOGY_MAX_ENUM : zink_primitive_topology(mode);
|
||||||
const unsigned idx = screen->info.dynamic_state3_props.dynamicPrimitiveTopologyUnrestricted ?
|
const unsigned idx = IS_MESH || screen->info.dynamic_state3_props.dynamicPrimitiveTopologyUnrestricted ?
|
||||||
0 :
|
0 :
|
||||||
get_pipeline_idx<DYNAMIC_STATE >= ZINK_DYNAMIC_STATE>(mode, vkmode);
|
get_pipeline_idx<DYNAMIC_STATE >= ZINK_DYNAMIC_STATE>(mode, vkmode);
|
||||||
assert(idx <= ARRAY_SIZE(prog->pipelines));
|
assert(idx <= ARRAY_SIZE(prog->pipelines));
|
||||||
if (!state->dirty && !state->modules_changed &&
|
if (IS_MESH) {
|
||||||
((DYNAMIC_STATE == ZINK_DYNAMIC_VERTEX_INPUT || DYNAMIC_STATE == ZINK_DYNAMIC_VERTEX_INPUT2) && !ctx->vertex_state_changed) &&
|
if (!state->mesh_dirty && !state->mesh_modules_changed)
|
||||||
idx == state->idx)
|
return state->mesh_pipeline;
|
||||||
return state->pipeline;
|
} else {
|
||||||
|
if (!state->dirty && !state->modules_changed && idx == state->idx && !ctx->vertex_state_changed &&
|
||||||
|
((DYNAMIC_STATE == ZINK_DYNAMIC_VERTEX_INPUT || DYNAMIC_STATE == ZINK_DYNAMIC_VERTEX_INPUT2)))
|
||||||
|
return state->pipeline;
|
||||||
|
}
|
||||||
|
|
||||||
struct hash_entry *entry = NULL;
|
struct hash_entry *entry = NULL;
|
||||||
|
|
||||||
/* recalc the base pipeline state hash */
|
/* recalc the base pipeline state hash */
|
||||||
if (state->dirty) {
|
if (IS_MESH) {
|
||||||
if (state->pipeline) //avoid on first hash
|
if (state->mesh_dirty) {
|
||||||
|
if (state->mesh_pipeline) //avoid on first hash
|
||||||
|
state->mesh_final_hash ^= state->mesh_hash;
|
||||||
|
state->mesh_hash = hash_gfx_pipeline_state<DYNAMIC_STATE>(state, screen);
|
||||||
|
state->mesh_final_hash ^= state->mesh_hash;
|
||||||
|
state->mesh_dirty = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (state->dirty) {
|
||||||
|
if (state->pipeline) //avoid on first hash
|
||||||
|
state->final_hash ^= state->hash;
|
||||||
|
state->hash = hash_gfx_pipeline_state<DYNAMIC_STATE>(state, screen);
|
||||||
state->final_hash ^= state->hash;
|
state->final_hash ^= state->hash;
|
||||||
state->hash = hash_gfx_pipeline_state<DYNAMIC_STATE>(state, screen);
|
state->dirty = false;
|
||||||
state->final_hash ^= state->hash;
|
}
|
||||||
state->dirty = false;
|
|
||||||
}
|
}
|
||||||
/* extra safety asserts for optimal path to catch refactoring bugs */
|
/* extra safety asserts for optimal path to catch refactoring bugs */
|
||||||
if (prog->optimal_keys) {
|
if (prog->optimal_keys) {
|
||||||
ASSERTED const union zink_shader_key_optimal *opt = (union zink_shader_key_optimal*)&prog->last_variant_hash;
|
ASSERTED const union zink_shader_key_optimal *opt = (union zink_shader_key_optimal*)&prog->last_variant_hash;
|
||||||
ASSERTED union zink_shader_key_optimal sanitized = {};
|
ASSERTED union zink_shader_key_optimal sanitized = {};
|
||||||
sanitized.val = zink_sanitize_optimal_key(ctx->gfx_stages, ctx->gfx_pipeline_state.shader_keys_optimal.key.val);
|
if (IS_MESH) {
|
||||||
|
sanitized.val = zink_sanitize_optimal_key_mesh(ctx->gfx_stages, ctx->gfx_pipeline_state.shader_keys_optimal.key.val);
|
||||||
|
assert(state->mesh_optimal_key == sanitized.val);
|
||||||
|
} else {
|
||||||
|
sanitized.val = zink_sanitize_optimal_key(ctx->gfx_stages, ctx->gfx_pipeline_state.shader_keys_optimal.key.val);
|
||||||
|
assert(state->optimal_key == sanitized.val);
|
||||||
|
}
|
||||||
assert(opt->val == sanitized.val);
|
assert(opt->val == sanitized.val);
|
||||||
assert(state->optimal_key == sanitized.val);
|
|
||||||
}
|
}
|
||||||
/* recalc vertex state if missing optimal extensions */
|
|
||||||
if (DYNAMIC_STATE != ZINK_DYNAMIC_VERTEX_INPUT2 && DYNAMIC_STATE != ZINK_DYNAMIC_VERTEX_INPUT && ctx->vertex_state_changed) {
|
if (IS_MESH) {
|
||||||
if (state->pipeline)
|
state->mesh_modules_changed = false;
|
||||||
state->final_hash ^= state->vertex_hash;
|
|
||||||
/* even if dynamic stride is available, it may not be usable with the current pipeline */
|
if (prog->last_finalized_hash[idx] == state->mesh_final_hash &&
|
||||||
if (DYNAMIC_STATE != ZINK_NO_DYNAMIC_STATE)
|
!prog->inline_variants && likely(prog->last_pipeline[idx]) &&
|
||||||
|
/* this data is too big to compare in the fast-path */
|
||||||
|
likely(!prog->shaders[MESA_SHADER_FRAGMENT]->fs.legacy_shadow_mask)) {
|
||||||
|
state->mesh_pipeline = prog->last_pipeline[idx]->pipeline;
|
||||||
|
return state->mesh_pipeline;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (DYNAMIC_STATE != ZINK_DYNAMIC_VERTEX_INPUT2 && DYNAMIC_STATE != ZINK_DYNAMIC_VERTEX_INPUT && ctx->vertex_state_changed) {
|
||||||
|
/* recalc vertex state if missing optimal extensions */
|
||||||
|
if (state->pipeline)
|
||||||
|
state->final_hash ^= state->vertex_hash;
|
||||||
|
/* even if dynamic stride is available, it may not be usable with the current pipeline */
|
||||||
|
if (DYNAMIC_STATE != ZINK_NO_DYNAMIC_STATE)
|
||||||
#if defined(MVK_VERSION)
|
#if defined(MVK_VERSION)
|
||||||
if (screen->have_dynamic_state_vertex_input_binding_stride)
|
if (screen->have_dynamic_state_vertex_input_binding_stride)
|
||||||
#endif
|
#endif
|
||||||
uses_dynamic_stride = check_vertex_strides(ctx);
|
uses_dynamic_stride = check_vertex_strides(ctx);
|
||||||
if (!uses_dynamic_stride) {
|
if (!uses_dynamic_stride) {
|
||||||
uint32_t hash = 0;
|
uint32_t hash = 0;
|
||||||
/* if we don't have dynamic states, we have to hash the enabled vertex buffer bindings */
|
/* if we don't have dynamic states, we have to hash the enabled vertex buffer bindings */
|
||||||
uint32_t vertex_buffers_enabled_mask = state->vertex_buffers_enabled_mask;
|
uint32_t vertex_buffers_enabled_mask = state->vertex_buffers_enabled_mask;
|
||||||
hash = XXH32(&vertex_buffers_enabled_mask, sizeof(uint32_t), hash);
|
hash = XXH32(&vertex_buffers_enabled_mask, sizeof(uint32_t), hash);
|
||||||
|
|
||||||
for (unsigned i = 0; i < state->element_state->num_bindings; i++) {
|
for (unsigned i = 0; i < state->element_state->num_bindings; i++) {
|
||||||
const unsigned buffer_id = ctx->element_state->hw_state.binding_map[i];
|
const unsigned buffer_id = ctx->element_state->hw_state.binding_map[i];
|
||||||
struct pipe_vertex_buffer *vb = ctx->vertex_buffers + buffer_id;
|
struct pipe_vertex_buffer *vb = ctx->vertex_buffers + buffer_id;
|
||||||
state->vertex_strides[buffer_id] = vb->buffer.resource ? state->element_state->b.strides[i] : 0;
|
state->vertex_strides[buffer_id] = vb->buffer.resource ? state->element_state->b.strides[i] : 0;
|
||||||
hash = XXH32(&state->vertex_strides[buffer_id], sizeof(uint32_t), hash);
|
hash = XXH32(&state->vertex_strides[buffer_id], sizeof(uint32_t), hash);
|
||||||
|
}
|
||||||
|
state->vertex_hash = hash ^ state->element_state->hash;
|
||||||
|
} else
|
||||||
|
state->vertex_hash = state->element_state->hash;
|
||||||
|
state->final_hash ^= state->vertex_hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
state->modules_changed = false;
|
||||||
|
state->uses_dynamic_stride = uses_dynamic_stride;
|
||||||
|
state->idx = idx;
|
||||||
|
|
||||||
|
/* shortcut for reusing previous pipeline across program changes */
|
||||||
|
if (DYNAMIC_STATE == ZINK_DYNAMIC_VERTEX_INPUT || DYNAMIC_STATE == ZINK_DYNAMIC_VERTEX_INPUT2) {
|
||||||
|
if (prog->last_finalized_hash[idx] == state->final_hash &&
|
||||||
|
!prog->inline_variants && likely(prog->last_pipeline[idx]) &&
|
||||||
|
/* this data is too big to compare in the fast-path */
|
||||||
|
likely(!prog->shaders[MESA_SHADER_FRAGMENT]->fs.legacy_shadow_mask)) {
|
||||||
|
state->pipeline = prog->last_pipeline[idx]->pipeline;
|
||||||
|
return state->pipeline;
|
||||||
}
|
}
|
||||||
state->vertex_hash = hash ^ state->element_state->hash;
|
|
||||||
} else
|
|
||||||
state->vertex_hash = state->element_state->hash;
|
|
||||||
state->final_hash ^= state->vertex_hash;
|
|
||||||
}
|
|
||||||
state->modules_changed = false;
|
|
||||||
state->uses_dynamic_stride = uses_dynamic_stride;
|
|
||||||
state->idx = idx;
|
|
||||||
|
|
||||||
/* shortcut for reusing previous pipeline across program changes */
|
|
||||||
if (DYNAMIC_STATE == ZINK_DYNAMIC_VERTEX_INPUT || DYNAMIC_STATE == ZINK_DYNAMIC_VERTEX_INPUT2) {
|
|
||||||
if (prog->last_finalized_hash[idx] == state->final_hash &&
|
|
||||||
!prog->inline_variants && likely(prog->last_pipeline[idx]) &&
|
|
||||||
/* this data is too big to compare in the fast-path */
|
|
||||||
likely(!prog->shaders[MESA_SHADER_FRAGMENT]->fs.legacy_shadow_mask)) {
|
|
||||||
state->pipeline = prog->last_pipeline[idx]->pipeline;
|
|
||||||
return state->pipeline;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
entry = _mesa_hash_table_search_pre_hashed(&prog->pipelines[idx], state->final_hash, state);
|
|
||||||
|
unsigned final_hash = IS_MESH ? state->mesh_final_hash : state->final_hash;
|
||||||
|
entry = _mesa_hash_table_search_pre_hashed(&prog->pipelines[idx], final_hash, state);
|
||||||
|
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
|
bool can_gpl = IS_MESH ? zink_can_use_pipeline_libs_mesh(ctx) : zink_can_use_pipeline_libs(ctx);
|
||||||
/* always wait on async precompile/cache fence */
|
/* always wait on async precompile/cache fence */
|
||||||
util_queue_fence_wait(&prog->base.cache_fence);
|
util_queue_fence_wait(&prog->base.cache_fence);
|
||||||
struct zink_gfx_pipeline_cache_entry *pc_entry = CALLOC_STRUCT(zink_gfx_pipeline_cache_entry);
|
struct zink_gfx_pipeline_cache_entry *pc_entry = CALLOC_STRUCT(zink_gfx_pipeline_cache_entry);
|
||||||
|
|
@ -194,14 +230,15 @@ zink_get_gfx_pipeline(struct zink_context *ctx,
|
||||||
pc_entry->prog = prog;
|
pc_entry->prog = prog;
|
||||||
/* init the optimized background compile fence */
|
/* init the optimized background compile fence */
|
||||||
util_queue_fence_init(&pc_entry->fence);
|
util_queue_fence_init(&pc_entry->fence);
|
||||||
entry = _mesa_hash_table_insert_pre_hashed(&prog->pipelines[idx], state->final_hash, pc_entry, pc_entry);
|
entry = _mesa_hash_table_insert_pre_hashed(&prog->pipelines[idx], final_hash, pc_entry, pc_entry);
|
||||||
if (prog->base.uses_shobj && !prog->is_separable) {
|
if (prog->base.uses_shobj && !prog->is_separable) {
|
||||||
memcpy(pc_entry->shobjs, prog->objs, sizeof(prog->objs));
|
memcpy(pc_entry->shobjs, prog->objs, sizeof(prog->objs));
|
||||||
zink_gfx_program_compile_queue(ctx, pc_entry);
|
zink_gfx_program_compile_queue(ctx, pc_entry);
|
||||||
} else if (HAVE_LIB && zink_can_use_pipeline_libs(ctx)) {
|
} else if (HAVE_LIB && can_gpl) {
|
||||||
|
uint32_t optimal_key = IS_MESH ? ctx->gfx_pipeline_state.mesh_optimal_key : ctx->gfx_pipeline_state.optimal_key;
|
||||||
/* this is the graphics pipeline library path: find/construct all partial pipelines */
|
/* this is the graphics pipeline library path: find/construct all partial pipelines */
|
||||||
simple_mtx_lock(&prog->libs->lock);
|
simple_mtx_lock(&prog->libs->lock);
|
||||||
struct set_entry *he = _mesa_set_search(&prog->libs->libs, &ctx->gfx_pipeline_state.optimal_key);
|
struct set_entry *he = _mesa_set_search(&prog->libs->libs, &optimal_key);
|
||||||
struct zink_gfx_library_key *gkey;
|
struct zink_gfx_library_key *gkey;
|
||||||
if (he) {
|
if (he) {
|
||||||
gkey = (struct zink_gfx_library_key *)he->key;
|
gkey = (struct zink_gfx_library_key *)he->key;
|
||||||
|
|
@ -210,7 +247,8 @@ zink_get_gfx_pipeline(struct zink_context *ctx,
|
||||||
gkey = zink_create_pipeline_lib(screen, prog, &ctx->gfx_pipeline_state);
|
gkey = zink_create_pipeline_lib(screen, prog, &ctx->gfx_pipeline_state);
|
||||||
}
|
}
|
||||||
simple_mtx_unlock(&prog->libs->lock);
|
simple_mtx_unlock(&prog->libs->lock);
|
||||||
struct zink_gfx_input_key *ikey = DYNAMIC_STATE == ZINK_DYNAMIC_VERTEX_INPUT ?
|
struct zink_gfx_input_key *ikey = IS_MESH ? zink_find_or_create_input_mesh(ctx) :
|
||||||
|
DYNAMIC_STATE == ZINK_DYNAMIC_VERTEX_INPUT ?
|
||||||
zink_find_or_create_input_dynamic(ctx, vkmode) :
|
zink_find_or_create_input_dynamic(ctx, vkmode) :
|
||||||
zink_find_or_create_input(ctx, vkmode);
|
zink_find_or_create_input(ctx, vkmode);
|
||||||
struct zink_gfx_output_key *okey = DYNAMIC_STATE >= ZINK_DYNAMIC_STATE3 && screen->have_full_ds3 ?
|
struct zink_gfx_output_key *okey = DYNAMIC_STATE >= ZINK_DYNAMIC_STATE3 && screen->have_full_ds3 ?
|
||||||
|
|
@ -232,7 +270,7 @@ zink_get_gfx_pipeline(struct zink_context *ctx,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* optimize by default only when expecting precompiles in order to reduce stuttering */
|
/* optimize by default only when expecting precompiles in order to reduce stuttering */
|
||||||
if (DYNAMIC_STATE != ZINK_DYNAMIC_VERTEX_INPUT2 && DYNAMIC_STATE != ZINK_DYNAMIC_VERTEX_INPUT)
|
if (DYNAMIC_STATE != ZINK_DYNAMIC_VERTEX_INPUT2 && DYNAMIC_STATE != ZINK_DYNAMIC_VERTEX_INPUT && !IS_MESH)
|
||||||
pc_entry->pipeline = zink_create_gfx_pipeline(screen, prog, prog->objs, state, state->element_state->binding_map, vkmode, !HAVE_LIB);
|
pc_entry->pipeline = zink_create_gfx_pipeline(screen, prog, prog->objs, state, state->element_state->binding_map, vkmode, !HAVE_LIB);
|
||||||
else
|
else
|
||||||
pc_entry->pipeline = zink_create_gfx_pipeline(screen, prog, prog->objs, state, NULL, vkmode, !HAVE_LIB);
|
pc_entry->pipeline = zink_create_gfx_pipeline(screen, prog, prog->objs, state, NULL, vkmode, !HAVE_LIB);
|
||||||
|
|
@ -250,7 +288,7 @@ zink_get_gfx_pipeline(struct zink_context *ctx,
|
||||||
state->pipeline = cache_entry->pipeline;
|
state->pipeline = cache_entry->pipeline;
|
||||||
/* update states for fastpath */
|
/* update states for fastpath */
|
||||||
if (DYNAMIC_STATE >= ZINK_DYNAMIC_VERTEX_INPUT) {
|
if (DYNAMIC_STATE >= ZINK_DYNAMIC_VERTEX_INPUT) {
|
||||||
prog->last_finalized_hash[idx] = state->final_hash;
|
prog->last_finalized_hash[idx] = final_hash;
|
||||||
prog->last_pipeline[idx] = cache_entry;
|
prog->last_pipeline[idx] = cache_entry;
|
||||||
}
|
}
|
||||||
return state->pipeline;
|
return state->pipeline;
|
||||||
|
|
@ -396,6 +434,8 @@ get_gfx_pipeline_stage_eq_func(struct zink_gfx_program *prog, bool optimal_keys)
|
||||||
equals_gfx_pipeline_state_func
|
equals_gfx_pipeline_state_func
|
||||||
zink_get_gfx_pipeline_eq_func(struct zink_screen *screen, struct zink_gfx_program *prog)
|
zink_get_gfx_pipeline_eq_func(struct zink_screen *screen, struct zink_gfx_program *prog)
|
||||||
{
|
{
|
||||||
|
if (prog->shaders[MESA_SHADER_MESH])
|
||||||
|
return get_gfx_pipeline_stage_eq_func<ZINK_PIPELINE_DYNAMIC_VERTEX_INPUT_PCP>(prog, screen->optimal_keys);
|
||||||
if (screen->info.have_EXT_extended_dynamic_state) {
|
if (screen->info.have_EXT_extended_dynamic_state) {
|
||||||
if (screen->info.have_EXT_extended_dynamic_state2) {
|
if (screen->info.have_EXT_extended_dynamic_state2) {
|
||||||
if (screen->info.have_EXT_extended_dynamic_state3) {
|
if (screen->info.have_EXT_extended_dynamic_state3) {
|
||||||
|
|
|
||||||
|
|
@ -1493,6 +1493,8 @@ zink_destroy_screen(struct pipe_screen *pscreen)
|
||||||
|
|
||||||
for (unsigned i = 0; i < ARRAY_SIZE(screen->pipeline_libs); i++)
|
for (unsigned i = 0; i < ARRAY_SIZE(screen->pipeline_libs); i++)
|
||||||
_mesa_set_fini(&screen->pipeline_libs[i], NULL);
|
_mesa_set_fini(&screen->pipeline_libs[i], NULL);
|
||||||
|
for (unsigned i = 0; i < ARRAY_SIZE(screen->mesh_pipeline_libs); i++)
|
||||||
|
_mesa_set_fini(&screen->mesh_pipeline_libs[i], NULL);
|
||||||
|
|
||||||
u_transfer_helper_destroy(pscreen->transfer_helper);
|
u_transfer_helper_destroy(pscreen->transfer_helper);
|
||||||
if (util_queue_is_initialized(&screen->cache_get_thread)) {
|
if (util_queue_is_initialized(&screen->cache_get_thread)) {
|
||||||
|
|
@ -3528,10 +3530,6 @@ zink_internal_create_screen(const struct pipe_screen_config *config, int64_t dev
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
zink_init_shader_caps(screen);
|
|
||||||
zink_init_compute_caps(screen);
|
|
||||||
zink_init_screen_caps(screen);
|
|
||||||
|
|
||||||
if (screen->info.have_EXT_sample_locations) {
|
if (screen->info.have_EXT_sample_locations) {
|
||||||
VkMultisamplePropertiesEXT prop;
|
VkMultisamplePropertiesEXT prop;
|
||||||
prop.sType = VK_STRUCTURE_TYPE_MULTISAMPLE_PROPERTIES_EXT;
|
prop.sType = VK_STRUCTURE_TYPE_MULTISAMPLE_PROPERTIES_EXT;
|
||||||
|
|
@ -3675,6 +3673,10 @@ zink_internal_create_screen(const struct pipe_screen_config *config, int64_t dev
|
||||||
|
|
||||||
init_optimal_keys(screen);
|
init_optimal_keys(screen);
|
||||||
|
|
||||||
|
zink_init_shader_caps(screen);
|
||||||
|
zink_init_compute_caps(screen);
|
||||||
|
zink_init_screen_caps(screen);
|
||||||
|
|
||||||
screen->screen_id = p_atomic_inc_return(&num_screens);
|
screen->screen_id = p_atomic_inc_return(&num_screens);
|
||||||
zink_tracing = screen->instance_info->have_EXT_debug_utils &&
|
zink_tracing = screen->instance_info->have_EXT_debug_utils &&
|
||||||
(u_trace_is_enabled(U_TRACE_TYPE_PERFETTO) || u_trace_is_enabled(U_TRACE_TYPE_MARKERS));
|
(u_trace_is_enabled(U_TRACE_TYPE_PERFETTO) || u_trace_is_enabled(U_TRACE_TYPE_MARKERS));
|
||||||
|
|
|
||||||
|
|
@ -155,6 +155,8 @@ union zink_shader_key_optimal {
|
||||||
|
|
||||||
/* the default key has only last_vertex_stage set*/
|
/* the default key has only last_vertex_stage set*/
|
||||||
#define ZINK_SHADER_KEY_OPTIMAL_DEFAULT (1<<0)
|
#define ZINK_SHADER_KEY_OPTIMAL_DEFAULT (1<<0)
|
||||||
|
/* mesh default key has no bits set */
|
||||||
|
#define ZINK_SHADER_KEY_OPTIMAL_DEFAULT_MESH (0)
|
||||||
/* Ignore patch_vertices bits that would only be used if we had to generate the missing TCS */
|
/* Ignore patch_vertices bits that would only be used if we had to generate the missing TCS */
|
||||||
static inline uint32_t
|
static inline uint32_t
|
||||||
zink_shader_key_optimal_no_tcs(uint32_t key)
|
zink_shader_key_optimal_no_tcs(uint32_t key)
|
||||||
|
|
@ -164,7 +166,17 @@ zink_shader_key_optimal_no_tcs(uint32_t key)
|
||||||
k.tcs_bits = 0;
|
k.tcs_bits = 0;
|
||||||
return k.val;
|
return k.val;
|
||||||
}
|
}
|
||||||
|
static inline uint32_t
|
||||||
|
zink_shader_key_optimal_mesh(uint32_t key)
|
||||||
|
{
|
||||||
|
union zink_shader_key_optimal k;
|
||||||
|
k.val = key;
|
||||||
|
k.vs_bits = 0;
|
||||||
|
k.tcs_bits = 0;
|
||||||
|
return k.val;
|
||||||
|
}
|
||||||
#define ZINK_SHADER_KEY_OPTIMAL_IS_DEFAULT(key) (zink_shader_key_optimal_no_tcs(key) == ZINK_SHADER_KEY_OPTIMAL_DEFAULT)
|
#define ZINK_SHADER_KEY_OPTIMAL_IS_DEFAULT(key) (zink_shader_key_optimal_no_tcs(key) == ZINK_SHADER_KEY_OPTIMAL_DEFAULT)
|
||||||
|
#define ZINK_SHADER_KEY_OPTIMAL_IS_DEFAULT_MESH(key) (zink_shader_key_optimal_mesh(key) == ZINK_SHADER_KEY_OPTIMAL_DEFAULT_MESH)
|
||||||
|
|
||||||
static inline const struct zink_fs_key_base *
|
static inline const struct zink_fs_key_base *
|
||||||
zink_fs_key_base(const struct zink_shader_key *key)
|
zink_fs_key_base(const struct zink_shader_key *key)
|
||||||
|
|
|
||||||
|
|
@ -640,7 +640,7 @@ zink_bind_rasterizer_state(struct pipe_context *pctx, void *cso)
|
||||||
|
|
||||||
if (clip_halfz != ctx->rast_state->base.clip_halfz) {
|
if (clip_halfz != ctx->rast_state->base.clip_halfz) {
|
||||||
if (screen->info.have_EXT_depth_clip_control)
|
if (screen->info.have_EXT_depth_clip_control)
|
||||||
ctx->gfx_pipeline_state.dirty = true;
|
ctx->gfx_pipeline_state.dirty = ctx->gfx_pipeline_state.mesh_dirty = true;
|
||||||
else
|
else
|
||||||
zink_set_last_vertex_key(ctx)->clip_halfz = ctx->rast_state->base.clip_halfz;
|
zink_set_last_vertex_key(ctx)->clip_halfz = ctx->rast_state->base.clip_halfz;
|
||||||
ctx->vp_state_changed = true;
|
ctx->vp_state_changed = true;
|
||||||
|
|
|
||||||
|
|
@ -103,6 +103,7 @@
|
||||||
enum zink_pipeline_idx {
|
enum zink_pipeline_idx {
|
||||||
ZINK_PIPELINE_GFX,
|
ZINK_PIPELINE_GFX,
|
||||||
ZINK_PIPELINE_COMPUTE,
|
ZINK_PIPELINE_COMPUTE,
|
||||||
|
ZINK_PIPELINE_MESH,
|
||||||
ZINK_PIPELINE_MAX,
|
ZINK_PIPELINE_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -431,8 +432,8 @@ struct zink_descriptor_data {
|
||||||
bool bindless_bound;
|
bool bindless_bound;
|
||||||
bool bindless_init;
|
bool bindless_init;
|
||||||
bool has_fbfetch;
|
bool has_fbfetch;
|
||||||
bool push_state_changed[ZINK_PIPELINE_MAX]; //gfx, compute
|
bool push_state_changed[ZINK_PIPELINE_MAX]; //gfx, compute, mesh
|
||||||
uint8_t state_changed[ZINK_PIPELINE_MAX]; //gfx, compute
|
uint8_t state_changed[ZINK_PIPELINE_MAX]; //gfx, compute, mesh
|
||||||
struct zink_descriptor_layout_key *push_layout_keys[2]; //gfx, compute
|
struct zink_descriptor_layout_key *push_layout_keys[2]; //gfx, compute
|
||||||
struct zink_descriptor_layout *push_dsl[2]; //gfx, compute
|
struct zink_descriptor_layout *push_dsl[2]; //gfx, compute
|
||||||
VkDescriptorUpdateTemplate push_template[2]; //gfx, compute
|
VkDescriptorUpdateTemplate push_template[2]; //gfx, compute
|
||||||
|
|
@ -454,13 +455,14 @@ struct zink_descriptor_data {
|
||||||
} db;
|
} db;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct zink_program *pg[ZINK_PIPELINE_MAX]; //gfx, compute
|
struct zink_program *pg[ZINK_PIPELINE_MAX]; //gfx, compute, mesh
|
||||||
|
|
||||||
VkDescriptorUpdateTemplateEntry push_entries[MESA_SHADER_STAGES]; //gfx+fbfetch
|
VkDescriptorUpdateTemplateEntry push_entries[MESA_SHADER_STAGES]; //gfx+fbfetch
|
||||||
VkDescriptorUpdateTemplateEntry compute_push_entry;
|
VkDescriptorUpdateTemplateEntry compute_push_entry;
|
||||||
|
VkDescriptorUpdateTemplateEntry mesh_push_entries[MESA_SHADER_STAGES]; //mesh+fbfetch
|
||||||
|
|
||||||
/* push descriptor layout size and binding offsets */
|
/* push descriptor layout size and binding offsets */
|
||||||
uint32_t db_size[ZINK_PIPELINE_MAX]; //gfx, compute
|
uint32_t db_size[ZINK_PIPELINE_MAX]; //gfx, compute, mesh
|
||||||
uint32_t db_offset[ZINK_GFX_SHADER_COUNT + 1]; //gfx + fbfetch
|
uint32_t db_offset[ZINK_GFX_SHADER_COUNT + 1]; //gfx + fbfetch
|
||||||
/* compute offset is always 0 */
|
/* compute offset is always 0 */
|
||||||
};
|
};
|
||||||
|
|
@ -520,20 +522,20 @@ struct zink_batch_descriptor_data {
|
||||||
unsigned pool_size[ZINK_DESCRIPTOR_BASE_TYPES];
|
unsigned pool_size[ZINK_DESCRIPTOR_BASE_TYPES];
|
||||||
/* this array is sized based on the max zink_descriptor_pool_key::id used by the batch; members may be NULL */
|
/* this array is sized based on the max zink_descriptor_pool_key::id used by the batch; members may be NULL */
|
||||||
struct util_dynarray pools[ZINK_DESCRIPTOR_BASE_TYPES];
|
struct util_dynarray pools[ZINK_DESCRIPTOR_BASE_TYPES];
|
||||||
struct zink_descriptor_pool_multi push_pool[2]; //gfx, compute
|
struct zink_descriptor_pool_multi push_pool[2]; //gfx, compute, mesh
|
||||||
/* the current program (for descriptor updating) */
|
/* the current program (for descriptor updating) */
|
||||||
struct zink_program *pg[ZINK_PIPELINE_MAX]; //gfx, compute
|
struct zink_program *pg[ZINK_PIPELINE_MAX]; //gfx, compute, mesh
|
||||||
/* the current pipeline compatibility id (for pipeline compatibility rules) */
|
/* the current pipeline compatibility id (for pipeline compatibility rules) */
|
||||||
uint32_t compat_id[ZINK_PIPELINE_MAX]; //gfx, compute
|
uint32_t compat_id[ZINK_PIPELINE_MAX]; //gfx, compute, mesh
|
||||||
/* the current set layout */
|
/* the current set layout */
|
||||||
VkDescriptorSetLayout dsl[ZINK_PIPELINE_MAX][ZINK_DESCRIPTOR_BASE_TYPES]; //gfx, compute
|
VkDescriptorSetLayout dsl[ZINK_PIPELINE_MAX][ZINK_DESCRIPTOR_BASE_TYPES]; //gfx, compute, mesh
|
||||||
union {
|
union {
|
||||||
/* the current set for a given type; used for rebinding if pipeline compat id changes and current set must be rebound */
|
/* the current set for a given type; used for rebinding if pipeline compat id changes and current set must be rebound */
|
||||||
VkDescriptorSet sets[ZINK_PIPELINE_MAX][ZINK_DESCRIPTOR_NON_BINDLESS_TYPES]; //gfx, compute
|
VkDescriptorSet sets[ZINK_PIPELINE_MAX][ZINK_DESCRIPTOR_NON_BINDLESS_TYPES]; //gfx, compute, mesh
|
||||||
uint64_t cur_db_offset[ZINK_DESCRIPTOR_NON_BINDLESS_TYPES]; //the current offset of a descriptor buffer for rebinds
|
uint64_t cur_db_offset[ZINK_DESCRIPTOR_NON_BINDLESS_TYPES]; //the current offset of a descriptor buffer for rebinds
|
||||||
};
|
};
|
||||||
/* mask of push descriptor usage */
|
/* mask of push descriptor usage */
|
||||||
unsigned push_usage[ZINK_PIPELINE_MAX]; //gfx, compute
|
unsigned push_usage[ZINK_PIPELINE_MAX]; //gfx, compute, mesh
|
||||||
|
|
||||||
struct zink_resource *db; //the descriptor buffer for a given type
|
struct zink_resource *db; //the descriptor buffer for a given type
|
||||||
uint8_t *db_map; //the host map for the buffer
|
uint8_t *db_map; //the host map for the buffer
|
||||||
|
|
@ -891,7 +893,9 @@ struct zink_gfx_pipeline_state {
|
||||||
/* Pre-hashed value for table lookup, invalid when zero.
|
/* Pre-hashed value for table lookup, invalid when zero.
|
||||||
* Members after this point are not included in pipeline state hash key */
|
* Members after this point are not included in pipeline state hash key */
|
||||||
uint32_t hash;
|
uint32_t hash;
|
||||||
|
uint32_t mesh_hash;
|
||||||
bool dirty;
|
bool dirty;
|
||||||
|
bool mesh_dirty;
|
||||||
|
|
||||||
struct zink_pipeline_dynamic_state1 dyn_state1;
|
struct zink_pipeline_dynamic_state1 dyn_state1;
|
||||||
|
|
||||||
|
|
@ -899,14 +903,18 @@ struct zink_gfx_pipeline_state {
|
||||||
struct zink_pipeline_dynamic_state3 dyn_state3;
|
struct zink_pipeline_dynamic_state3 dyn_state3;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
VkShaderModule modules[MESA_SHADER_STAGES - 1];
|
VkShaderModule modules[MESA_SHADER_MESH_STAGES - 1];
|
||||||
uint32_t optimal_key;
|
uint32_t optimal_key;
|
||||||
};
|
};
|
||||||
|
uint32_t mesh_optimal_key;
|
||||||
|
|
||||||
bool modules_changed;
|
bool modules_changed;
|
||||||
|
bool mesh_modules_changed;
|
||||||
|
|
||||||
uint32_t vertex_hash;
|
uint32_t vertex_hash;
|
||||||
|
|
||||||
uint32_t final_hash;
|
uint32_t final_hash;
|
||||||
|
uint32_t mesh_final_hash;
|
||||||
|
|
||||||
uint32_t _pad2;
|
uint32_t _pad2;
|
||||||
/* order matches zink_gfx_input_key */
|
/* order matches zink_gfx_input_key */
|
||||||
|
|
@ -936,6 +944,7 @@ struct zink_gfx_pipeline_state {
|
||||||
VkFormat rendering_formats[PIPE_MAX_COLOR_BUFS];
|
VkFormat rendering_formats[PIPE_MAX_COLOR_BUFS];
|
||||||
VkPipelineRenderingCreateInfo rendering_info;
|
VkPipelineRenderingCreateInfo rendering_info;
|
||||||
VkPipeline pipeline;
|
VkPipeline pipeline;
|
||||||
|
VkPipeline mesh_pipeline;
|
||||||
enum mesa_prim gfx_prim_mode; //pending mode
|
enum mesa_prim gfx_prim_mode; //pending mode
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1034,7 +1043,7 @@ typedef bool (*equals_gfx_pipeline_state_func)(const void *a, const void *b);
|
||||||
|
|
||||||
struct zink_gfx_library_key {
|
struct zink_gfx_library_key {
|
||||||
uint32_t optimal_key; //equals_pipeline_lib_optimal
|
uint32_t optimal_key; //equals_pipeline_lib_optimal
|
||||||
VkShaderModule modules[ZINK_GFX_SHADER_COUNT];
|
VkShaderModule modules[MESA_SHADER_MESH_STAGES];
|
||||||
VkPipeline pipeline;
|
VkPipeline pipeline;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1086,13 +1095,13 @@ struct zink_gfx_pipeline_cache_entry {
|
||||||
struct zink_gfx_output_key *okey;
|
struct zink_gfx_output_key *okey;
|
||||||
VkPipeline unoptimized_pipeline;
|
VkPipeline unoptimized_pipeline;
|
||||||
} gpl;
|
} gpl;
|
||||||
struct zink_shader_object shobjs[ZINK_GFX_SHADER_COUNT];
|
struct zink_shader_object shobjs[MESA_SHADER_MESH_STAGES];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct zink_gfx_lib_cache {
|
struct zink_gfx_lib_cache {
|
||||||
/* for hashing */
|
/* for hashing */
|
||||||
struct zink_shader *shaders[ZINK_GFX_SHADER_COUNT];
|
struct zink_shader *shaders[MESA_SHADER_MESH_STAGES];
|
||||||
unsigned refcount;
|
unsigned refcount;
|
||||||
bool removed; //once removed from cache
|
bool removed; //once removed from cache
|
||||||
uint8_t stages_present;
|
uint8_t stages_present;
|
||||||
|
|
@ -1110,16 +1119,16 @@ struct zink_gfx_program {
|
||||||
uint32_t stages_remaining; //mask of zink_shader remaining in this program
|
uint32_t stages_remaining; //mask of zink_shader remaining in this program
|
||||||
uint32_t gfx_hash; //from ctx->gfx_hash
|
uint32_t gfx_hash; //from ctx->gfx_hash
|
||||||
|
|
||||||
struct zink_shader *shaders[ZINK_GFX_SHADER_COUNT];
|
struct zink_shader *shaders[MESA_SHADER_MESH_STAGES];
|
||||||
struct zink_shader *last_vertex_stage;
|
struct zink_shader *last_vertex_stage;
|
||||||
struct zink_shader_object objs[ZINK_GFX_SHADER_COUNT];
|
struct zink_shader_object objs[MESA_SHADER_MESH_STAGES];
|
||||||
|
|
||||||
/* full */
|
/* full */
|
||||||
VkShaderEXT objects[ZINK_GFX_SHADER_COUNT];
|
VkShaderEXT objects[MESA_SHADER_MESH_STAGES];
|
||||||
uint32_t module_hash[ZINK_GFX_SHADER_COUNT];
|
uint32_t module_hash[MESA_SHADER_MESH_STAGES];
|
||||||
struct blob blobs[ZINK_GFX_SHADER_COUNT];
|
struct blob blobs[MESA_SHADER_MESH_STAGES];
|
||||||
struct util_dynarray shader_cache[ZINK_GFX_SHADER_COUNT][2][2]; //normal, nonseamless cubes, inline uniforms
|
struct util_dynarray shader_cache[MESA_SHADER_MESH_STAGES][2][2]; //normal, nonseamless cubes, inline uniforms
|
||||||
unsigned inlined_variant_count[ZINK_GFX_SHADER_COUNT];
|
unsigned inlined_variant_count[MESA_SHADER_MESH_STAGES];
|
||||||
uint32_t default_variant_hash;
|
uint32_t default_variant_hash;
|
||||||
uint8_t inline_variants; //which stages are using inlined uniforms
|
uint8_t inline_variants; //which stages are using inlined uniforms
|
||||||
bool needs_inlining; // whether this program requires some uniforms to be inlined
|
bool needs_inlining; // whether this program requires some uniforms to be inlined
|
||||||
|
|
@ -1253,6 +1262,7 @@ struct zink_resource_object {
|
||||||
bool is_aux;
|
bool is_aux;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* "gfx" includes mesh here */
|
||||||
struct zink_resource {
|
struct zink_resource {
|
||||||
struct threaded_resource base;
|
struct threaded_resource base;
|
||||||
|
|
||||||
|
|
@ -1271,8 +1281,8 @@ struct zink_resource {
|
||||||
uint8_t vbo_bind_count;
|
uint8_t vbo_bind_count;
|
||||||
uint8_t so_bind_count; //not counted in all_binds
|
uint8_t so_bind_count; //not counted in all_binds
|
||||||
bool so_valid;
|
bool so_valid;
|
||||||
uint32_t ubo_bind_mask[MESA_SHADER_STAGES];
|
uint32_t ubo_bind_mask[MESA_SHADER_MESH_STAGES];
|
||||||
uint32_t ssbo_bind_mask[MESA_SHADER_STAGES];
|
uint32_t ssbo_bind_mask[MESA_SHADER_MESH_STAGES];
|
||||||
};
|
};
|
||||||
struct {
|
struct {
|
||||||
bool linear;
|
bool linear;
|
||||||
|
|
@ -1286,8 +1296,8 @@ struct zink_resource {
|
||||||
VkImageAspectFlags aspect;
|
VkImageAspectFlags aspect;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
uint32_t sampler_binds[MESA_SHADER_STAGES];
|
uint32_t sampler_binds[MESA_SHADER_MESH_STAGES];
|
||||||
uint32_t image_binds[MESA_SHADER_STAGES];
|
uint32_t image_binds[MESA_SHADER_MESH_STAGES];
|
||||||
uint16_t sampler_bind_count[2]; //gfx, compute
|
uint16_t sampler_bind_count[2]; //gfx, compute
|
||||||
uint16_t image_bind_count[2]; //gfx, compute
|
uint16_t image_bind_count[2]; //gfx, compute
|
||||||
uint16_t write_bind_count[2]; //gfx, compute
|
uint16_t write_bind_count[2]; //gfx, compute
|
||||||
|
|
@ -1404,6 +1414,10 @@ struct zink_screen {
|
||||||
struct set pipeline_libs[8];
|
struct set pipeline_libs[8];
|
||||||
simple_mtx_t pipeline_libs_lock[8];
|
simple_mtx_t pipeline_libs_lock[8];
|
||||||
|
|
||||||
|
/* there is only [task] and [notask]*/
|
||||||
|
struct set mesh_pipeline_libs[2];
|
||||||
|
simple_mtx_t mesh_pipeline_libs_lock[2];
|
||||||
|
|
||||||
simple_mtx_t desc_set_layouts_lock;
|
simple_mtx_t desc_set_layouts_lock;
|
||||||
struct hash_table desc_set_layouts[ZINK_DESCRIPTOR_BASE_TYPES];
|
struct hash_table desc_set_layouts[ZINK_DESCRIPTOR_BASE_TYPES];
|
||||||
simple_mtx_t desc_pool_keys_lock;
|
simple_mtx_t desc_pool_keys_lock;
|
||||||
|
|
@ -1638,6 +1652,7 @@ struct zink_viewport_state {
|
||||||
struct pipe_viewport_state viewport_states[PIPE_MAX_VIEWPORTS];
|
struct pipe_viewport_state viewport_states[PIPE_MAX_VIEWPORTS];
|
||||||
struct pipe_scissor_state scissor_states[PIPE_MAX_VIEWPORTS];
|
struct pipe_scissor_state scissor_states[PIPE_MAX_VIEWPORTS];
|
||||||
uint8_t num_viewports;
|
uint8_t num_viewports;
|
||||||
|
uint8_t mesh_num_viewports;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct zink_descriptor_db_info {
|
struct zink_descriptor_db_info {
|
||||||
|
|
@ -1679,6 +1694,7 @@ typedef void (*pipe_draw_vertex_state_func)(struct pipe_context *ctx,
|
||||||
unsigned num_draws);
|
unsigned num_draws);
|
||||||
typedef void (*pipe_launch_grid_func)(struct pipe_context *pipe, const struct pipe_grid_info *info);
|
typedef void (*pipe_launch_grid_func)(struct pipe_context *pipe, const struct pipe_grid_info *info);
|
||||||
|
|
||||||
|
typedef void (*pipe_draw_mesh_tasks_func)(struct pipe_context *pipe, const struct pipe_grid_info *info);
|
||||||
|
|
||||||
enum zink_ds3_state {
|
enum zink_ds3_state {
|
||||||
ZINK_DS3_RAST_STIPPLE,
|
ZINK_DS3_RAST_STIPPLE,
|
||||||
|
|
@ -1711,6 +1727,7 @@ struct zink_context {
|
||||||
pipe_draw_func draw_vbo[2]; //batch changed
|
pipe_draw_func draw_vbo[2]; //batch changed
|
||||||
pipe_draw_vertex_state_func draw_state[2]; //batch changed
|
pipe_draw_vertex_state_func draw_state[2]; //batch changed
|
||||||
pipe_launch_grid_func launch_grid[2]; //batch changed
|
pipe_launch_grid_func launch_grid[2]; //batch changed
|
||||||
|
pipe_draw_mesh_tasks_func draw_mesh_tasks[2]; //batch changed
|
||||||
|
|
||||||
struct pipe_device_reset_callback reset;
|
struct pipe_device_reset_callback reset;
|
||||||
|
|
||||||
|
|
@ -1732,10 +1749,10 @@ struct zink_context {
|
||||||
unsigned shader_has_inlinable_uniforms_mask;
|
unsigned shader_has_inlinable_uniforms_mask;
|
||||||
unsigned inlinable_uniforms_valid_mask;
|
unsigned inlinable_uniforms_valid_mask;
|
||||||
|
|
||||||
struct pipe_constant_buffer ubos[MESA_SHADER_STAGES][PIPE_MAX_CONSTANT_BUFFERS];
|
struct pipe_constant_buffer ubos[MESA_SHADER_MESH_STAGES][PIPE_MAX_CONSTANT_BUFFERS];
|
||||||
struct pipe_shader_buffer ssbos[MESA_SHADER_STAGES][PIPE_MAX_SHADER_BUFFERS];
|
struct pipe_shader_buffer ssbos[MESA_SHADER_MESH_STAGES][PIPE_MAX_SHADER_BUFFERS];
|
||||||
uint32_t writable_ssbos[MESA_SHADER_STAGES];
|
uint32_t writable_ssbos[MESA_SHADER_MESH_STAGES];
|
||||||
struct zink_image_view image_views[MESA_SHADER_STAGES][ZINK_MAX_SHADER_IMAGES];
|
struct zink_image_view image_views[MESA_SHADER_MESH_STAGES][ZINK_MAX_SHADER_IMAGES];
|
||||||
|
|
||||||
uint32_t transient_attachments;
|
uint32_t transient_attachments;
|
||||||
struct pipe_framebuffer_state fb_state;
|
struct pipe_framebuffer_state fb_state;
|
||||||
|
|
@ -1747,9 +1764,9 @@ struct zink_context {
|
||||||
struct zink_depth_stencil_alpha_state *dsa_state;
|
struct zink_depth_stencil_alpha_state *dsa_state;
|
||||||
|
|
||||||
bool has_swapchain;
|
bool has_swapchain;
|
||||||
bool pipeline_changed[ZINK_PIPELINE_MAX]; //gfx, compute
|
bool pipeline_changed[ZINK_PIPELINE_MAX]; //gfx, compute, mesh
|
||||||
|
|
||||||
struct zink_shader *gfx_stages[ZINK_GFX_SHADER_COUNT];
|
struct zink_shader *gfx_stages[MESA_SHADER_MESH_STAGES];
|
||||||
struct zink_shader *last_vertex_stage;
|
struct zink_shader *last_vertex_stage;
|
||||||
bool shader_reads_drawid;
|
bool shader_reads_drawid;
|
||||||
bool shader_reads_basevertex;
|
bool shader_reads_basevertex;
|
||||||
|
|
@ -1764,13 +1781,20 @@ struct zink_context {
|
||||||
struct set gfx_inputs;
|
struct set gfx_inputs;
|
||||||
struct set gfx_outputs;
|
struct set gfx_outputs;
|
||||||
|
|
||||||
|
/* the only possibilities are [no-task][task] */
|
||||||
|
struct hash_table mesh_cache[2];
|
||||||
|
simple_mtx_t mesh_lock[2];
|
||||||
|
uint32_t mesh_hash;
|
||||||
|
struct zink_gfx_program *mesh_program;
|
||||||
|
|
||||||
struct zink_descriptor_data dd;
|
struct zink_descriptor_data dd;
|
||||||
|
|
||||||
struct zink_compute_pipeline_state compute_pipeline_state;
|
struct zink_compute_pipeline_state compute_pipeline_state;
|
||||||
struct zink_compute_program *curr_compute;
|
struct zink_compute_program *curr_compute;
|
||||||
|
|
||||||
unsigned shader_stages : ZINK_GFX_SHADER_COUNT; /* mask of bound gfx shader stages */
|
uint8_t shader_stages; /* mask of bound gfx shader stages */
|
||||||
uint8_t dirty_gfx_stages; /* mask of changed gfx shader stages */
|
uint8_t dirty_gfx_stages; /* mask of changed gfx shader stages */
|
||||||
|
uint8_t dirty_mesh_stages; /* mask of changed mesh shader stages */
|
||||||
bool last_vertex_stage_dirty;
|
bool last_vertex_stage_dirty;
|
||||||
bool compute_dirty;
|
bool compute_dirty;
|
||||||
bool is_generated_gs_bound;
|
bool is_generated_gs_bound;
|
||||||
|
|
@ -1804,8 +1828,8 @@ struct zink_context {
|
||||||
struct pipe_vertex_buffer vertex_buffers[PIPE_MAX_ATTRIBS];
|
struct pipe_vertex_buffer vertex_buffers[PIPE_MAX_ATTRIBS];
|
||||||
bool vertex_buffers_dirty;
|
bool vertex_buffers_dirty;
|
||||||
|
|
||||||
struct zink_sampler_state *sampler_states[MESA_SHADER_STAGES][PIPE_MAX_SAMPLERS];
|
struct zink_sampler_state *sampler_states[MESA_SHADER_MESH_STAGES][PIPE_MAX_SAMPLERS];
|
||||||
struct pipe_sampler_view *sampler_views[MESA_SHADER_STAGES][PIPE_MAX_SAMPLERS];
|
struct pipe_sampler_view *sampler_views[MESA_SHADER_MESH_STAGES][PIPE_MAX_SAMPLERS];
|
||||||
|
|
||||||
struct zink_viewport_state vp_state;
|
struct zink_viewport_state vp_state;
|
||||||
bool vp_state_changed;
|
bool vp_state_changed;
|
||||||
|
|
@ -1861,32 +1885,32 @@ struct zink_context {
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
/* descriptor info */
|
/* descriptor info */
|
||||||
uint8_t num_ubos[MESA_SHADER_STAGES];
|
uint8_t num_ubos[MESA_SHADER_MESH_STAGES];
|
||||||
|
|
||||||
uint8_t num_ssbos[MESA_SHADER_STAGES];
|
uint8_t num_ssbos[MESA_SHADER_MESH_STAGES];
|
||||||
struct util_dynarray global_bindings;
|
struct util_dynarray global_bindings;
|
||||||
|
|
||||||
VkDescriptorImageInfo textures[MESA_SHADER_STAGES][PIPE_MAX_SAMPLERS];
|
VkDescriptorImageInfo textures[MESA_SHADER_MESH_STAGES][PIPE_MAX_SAMPLERS];
|
||||||
uint32_t emulate_nonseamless[MESA_SHADER_STAGES];
|
uint32_t emulate_nonseamless[MESA_SHADER_MESH_STAGES];
|
||||||
uint32_t cubes[MESA_SHADER_STAGES];
|
uint32_t cubes[MESA_SHADER_MESH_STAGES];
|
||||||
uint8_t num_samplers[MESA_SHADER_STAGES];
|
uint8_t num_samplers[MESA_SHADER_MESH_STAGES];
|
||||||
uint8_t num_sampler_views[MESA_SHADER_STAGES];
|
uint8_t num_sampler_views[MESA_SHADER_MESH_STAGES];
|
||||||
|
|
||||||
VkDescriptorImageInfo images[MESA_SHADER_STAGES][ZINK_MAX_SHADER_IMAGES];
|
VkDescriptorImageInfo images[MESA_SHADER_MESH_STAGES][ZINK_MAX_SHADER_IMAGES];
|
||||||
uint8_t num_images[MESA_SHADER_STAGES];
|
uint8_t num_images[MESA_SHADER_MESH_STAGES];
|
||||||
|
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
VkDescriptorBufferInfo ubos[MESA_SHADER_STAGES][PIPE_MAX_CONSTANT_BUFFERS];
|
VkDescriptorBufferInfo ubos[MESA_SHADER_MESH_STAGES][PIPE_MAX_CONSTANT_BUFFERS];
|
||||||
VkDescriptorBufferInfo ssbos[MESA_SHADER_STAGES][PIPE_MAX_SHADER_BUFFERS];
|
VkDescriptorBufferInfo ssbos[MESA_SHADER_MESH_STAGES][PIPE_MAX_SHADER_BUFFERS];
|
||||||
VkBufferView tbos[MESA_SHADER_STAGES][PIPE_MAX_SAMPLERS];
|
VkBufferView tbos[MESA_SHADER_MESH_STAGES][PIPE_MAX_SAMPLERS];
|
||||||
VkBufferView texel_images[MESA_SHADER_STAGES][ZINK_MAX_SHADER_IMAGES];
|
VkBufferView texel_images[MESA_SHADER_MESH_STAGES][ZINK_MAX_SHADER_IMAGES];
|
||||||
} t;
|
} t;
|
||||||
struct {
|
struct {
|
||||||
VkDescriptorAddressInfoEXT ubos[MESA_SHADER_STAGES][PIPE_MAX_CONSTANT_BUFFERS];
|
VkDescriptorAddressInfoEXT ubos[MESA_SHADER_MESH_STAGES][PIPE_MAX_CONSTANT_BUFFERS];
|
||||||
VkDescriptorAddressInfoEXT ssbos[MESA_SHADER_STAGES][PIPE_MAX_SHADER_BUFFERS];
|
VkDescriptorAddressInfoEXT ssbos[MESA_SHADER_MESH_STAGES][PIPE_MAX_SHADER_BUFFERS];
|
||||||
VkDescriptorAddressInfoEXT tbos[MESA_SHADER_STAGES][PIPE_MAX_SAMPLERS];
|
VkDescriptorAddressInfoEXT tbos[MESA_SHADER_MESH_STAGES][PIPE_MAX_SAMPLERS];
|
||||||
VkDescriptorAddressInfoEXT texel_images[MESA_SHADER_STAGES][ZINK_MAX_SHADER_IMAGES];
|
VkDescriptorAddressInfoEXT texel_images[MESA_SHADER_MESH_STAGES][ZINK_MAX_SHADER_IMAGES];
|
||||||
} db;
|
} db;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1894,9 +1918,9 @@ struct zink_context {
|
||||||
uint8_t fbfetch_db[ZINK_FBFETCH_DESCRIPTOR_SIZE];
|
uint8_t fbfetch_db[ZINK_FBFETCH_DESCRIPTOR_SIZE];
|
||||||
|
|
||||||
/* the current state of the zs swizzle data */
|
/* the current state of the zs swizzle data */
|
||||||
struct zink_zs_swizzle_key zs_swizzle[MESA_SHADER_STAGES];
|
struct zink_zs_swizzle_key zs_swizzle[MESA_SHADER_MESH_STAGES];
|
||||||
|
|
||||||
struct zink_resource *descriptor_res[ZINK_DESCRIPTOR_BASE_TYPES][MESA_SHADER_STAGES][PIPE_MAX_SAMPLERS];
|
struct zink_resource *descriptor_res[ZINK_DESCRIPTOR_BASE_TYPES][MESA_SHADER_MESH_STAGES][PIPE_MAX_SAMPLERS];
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct util_idalloc tex_slots; //img, buffer
|
struct util_idalloc tex_slots; //img, buffer
|
||||||
|
|
@ -1923,6 +1947,7 @@ struct zink_context {
|
||||||
bool null_fbfetch_init;
|
bool null_fbfetch_init;
|
||||||
} di;
|
} di;
|
||||||
void (*invalidate_descriptor_state)(struct zink_context *ctx, mesa_shader_stage shader, enum zink_descriptor_type type, unsigned, unsigned);
|
void (*invalidate_descriptor_state)(struct zink_context *ctx, mesa_shader_stage shader, enum zink_descriptor_type type, unsigned, unsigned);
|
||||||
|
/* "gfx" includes mesh */
|
||||||
struct set *need_barriers[2]; //gfx, compute
|
struct set *need_barriers[2]; //gfx, compute
|
||||||
struct set update_barriers[2][2]; //[gfx, compute][current, next]
|
struct set update_barriers[2][2]; //[gfx, compute][current, next]
|
||||||
uint8_t barrier_set_idx[2];
|
uint8_t barrier_set_idx[2];
|
||||||
|
|
@ -1939,6 +1964,7 @@ struct zink_context {
|
||||||
bool dirty_so_targets;
|
bool dirty_so_targets;
|
||||||
|
|
||||||
bool gfx_dirty;
|
bool gfx_dirty;
|
||||||
|
bool mesh_dirty;
|
||||||
|
|
||||||
bool shobj_draw : 1; //using shader objects for draw
|
bool shobj_draw : 1; //using shader objects for draw
|
||||||
bool is_device_lost;
|
bool is_device_lost;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue