shader: resolve shader dependencies before program linking

Shader programs are submitted for linking in the host driver twice as
frequently as for native applications due to circular shader
dependencies, immediate TGSI conversion, and explicit shader variant
selection ordering at draw-time.

Circular dependencies are resolved by re-running shader variant
selection twice before emitting calling glUseProgram() in the host.

The cost of this workaround is that GLSL is still emitted to the host
driver for compilation into intermediate/native instructions even for
unused shader variants, but the extraneous linking has been eliminated.

Workaround for #180.

v2: changed shader select order on second pass; only select frag shader
once.

Signed-off-by: Ryan Neph <ryanneph@google.com>
Reviewed-by: Gert Wollny <gert.wollny@collabora.com>
macos/master
Ryan Neph 4 years ago committed by Gert Wollny
parent 22cbf5fc12
commit 2d99aa61c6
  1. 16
      src/vrend_renderer.c

@ -4519,6 +4519,22 @@ vrend_select_program(struct vrend_sub_context *sub_ctx, const struct pipe_draw_i
vrend_shader_select(sub_ctx, shaders[PIPE_SHADER_GEOMETRY], &gs_dirty); vrend_shader_select(sub_ctx, shaders[PIPE_SHADER_GEOMETRY], &gs_dirty);
vrend_shader_select(sub_ctx, shaders[PIPE_SHADER_FRAGMENT], &fs_dirty); vrend_shader_select(sub_ctx, shaders[PIPE_SHADER_FRAGMENT], &fs_dirty);
// NOTE: run shader selection again as a workaround to #180 - "duplicated shader compilation"
if (shaders[PIPE_SHADER_GEOMETRY])
vrend_shader_select(sub_ctx, shaders[PIPE_SHADER_GEOMETRY], &gs_dirty);
if (shaders[PIPE_SHADER_TESS_EVAL])
vrend_shader_select(sub_ctx, shaders[PIPE_SHADER_TESS_EVAL], &tes_dirty);
if (shaders[PIPE_SHADER_TESS_CTRL] && shaders[PIPE_SHADER_TESS_CTRL]->tokens)
vrend_shader_select(sub_ctx, shaders[PIPE_SHADER_TESS_CTRL], &tcs_dirty);
else if (vrend_state.use_gles && shaders[PIPE_SHADER_TESS_EVAL]) {
VREND_DEBUG(dbg_shader, sub_ctx->parent, "Need to inject a TCS\n");
vrend_inject_tcs(sub_ctx, info->vertices_per_patch);
}
sub_ctx->drawing = true;
vrend_shader_select(sub_ctx, shaders[PIPE_SHADER_VERTEX], &vs_dirty);
sub_ctx->drawing = false;
if (!shaders[PIPE_SHADER_VERTEX]->current || if (!shaders[PIPE_SHADER_VERTEX]->current ||
!shaders[PIPE_SHADER_FRAGMENT]->current || !shaders[PIPE_SHADER_FRAGMENT]->current ||
(shaders[PIPE_SHADER_GEOMETRY] && !shaders[PIPE_SHADER_GEOMETRY]->current) || (shaders[PIPE_SHADER_GEOMETRY] && !shaders[PIPE_SHADER_GEOMETRY]->current) ||

Loading…
Cancel
Save