[virglrenderer-devel] [PATCH 19/21] tessellation: add shader building support for tess eval/ctrl. (v2)
Dave Airlie
airlied at gmail.com
Mon Jun 11 05:11:10 UTC 2018
From: Dave Airlie <airlied at redhat.com>
This adds all the shader program building and dirtying for
tess shaders.
The big change is building the key so that we get the correct
tess input/output blocks.
It might be possible SSO could reduce some of that overheads
v2: fixup warnings
---
src/vrend_renderer.c | 159 +++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 143 insertions(+), 16 deletions(-)
diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c
index b756c10..33883a3 100644
--- a/src/vrend_renderer.c
+++ b/src/vrend_renderer.c
@@ -864,7 +864,9 @@ static void set_stream_out_varyings(int prog_id, struct vrend_shader_info *sinfo
static struct vrend_linked_shader_program *add_shader_program(struct vrend_context *ctx,
struct vrend_shader *vs,
struct vrend_shader *fs,
- struct vrend_shader *gs)
+ struct vrend_shader *gs,
+ struct vrend_shader *tcs,
+ struct vrend_shader *tes)
{
struct vrend_linked_shader_program *sprog = CALLOC_STRUCT(vrend_linked_shader_program);
char name[64];
@@ -880,7 +882,9 @@ static struct vrend_linked_shader_program *add_shader_program(struct vrend_conte
/* need to rewrite VS code to add interpolation params */
if (gs && gs->compiled_fs_id != fs->id)
do_patch = true;
- if (!gs && vs->compiled_fs_id != fs->id)
+ if (!gs && tes && tes->compiled_fs_id != fs->id)
+ do_patch = true;
+ if (!gs && !tes && vs->compiled_fs_id != fs->id)
do_patch = true;
if (do_patch) {
@@ -890,24 +894,35 @@ static struct vrend_linked_shader_program *add_shader_program(struct vrend_conte
vrend_patch_vertex_shader_interpolants(&ctx->shader_cfg, gs->glsl_prog,
&gs->sel->sinfo,
&fs->sel->sinfo, "gso", fs->key.flatshade);
+ else if (tes)
+ vrend_patch_vertex_shader_interpolants(&ctx->shader_cfg, tes->glsl_prog,
+ &tes->sel->sinfo,
+ &fs->sel->sinfo, "teo", fs->key.flatshade);
else
vrend_patch_vertex_shader_interpolants(&ctx->shader_cfg, vs->glsl_prog,
&vs->sel->sinfo,
&fs->sel->sinfo, "vso", fs->key.flatshade);
- ret = vrend_compile_shader(ctx, gs ? gs : vs);
+ ret = vrend_compile_shader(ctx, gs ? gs : (tes ? tes : vs));
if (ret == false) {
- glDeleteShader(gs ? gs->id : vs->id);
+ glDeleteShader(gs ? gs->id : (tes ? tes->id : vs->id));
free(sprog);
return NULL;
}
if (gs)
gs->compiled_fs_id = fs->id;
+ else if (tes)
+ tes->compiled_fs_id = fs->id;
else
vs->compiled_fs_id = fs->id;
}
prog_id = glCreateProgram();
glAttachShader(prog_id, vs->id);
+ if (tcs && tcs->id > 0)
+ glAttachShader(prog_id, tcs->id);
+ if (tes && tes->id > 0)
+ glAttachShader(prog_id, tes->id);
+
if (gs) {
if (gs->id > 0)
glAttachShader(prog_id, gs->id);
@@ -961,13 +976,19 @@ static struct vrend_linked_shader_program *add_shader_program(struct vrend_conte
sprog->ss[PIPE_SHADER_VERTEX] = vs;
sprog->ss[PIPE_SHADER_FRAGMENT] = fs;
sprog->ss[PIPE_SHADER_GEOMETRY] = gs;
+ sprog->ss[PIPE_SHADER_TESS_CTRL] = tcs;
+ sprog->ss[PIPE_SHADER_TESS_EVAL] = tes;
list_add(&sprog->sl[PIPE_SHADER_VERTEX], &vs->programs);
list_add(&sprog->sl[PIPE_SHADER_FRAGMENT], &fs->programs);
if (gs)
list_add(&sprog->sl[PIPE_SHADER_GEOMETRY], &gs->programs);
+ if (tcs)
+ list_add(&sprog->sl[PIPE_SHADER_TESS_CTRL], &tcs->programs);
+ if (tes)
+ list_add(&sprog->sl[PIPE_SHADER_TESS_EVAL], &tes->programs);
- last_shader = gs ? PIPE_SHADER_GEOMETRY : PIPE_SHADER_FRAGMENT;
+ last_shader = tes ? PIPE_SHADER_TESS_EVAL : (gs ? PIPE_SHADER_GEOMETRY : PIPE_SHADER_FRAGMENT);
sprog->id = prog_id;
list_addtail(&sprog->head, &ctx->sub->programs);
@@ -978,6 +999,8 @@ static struct vrend_linked_shader_program *add_shader_program(struct vrend_conte
sprog->fs_stipple_loc = -1;
sprog->vs_ws_adjust_loc = glGetUniformLocation(prog_id, "winsys_adjust_y");
for (id = PIPE_SHADER_VERTEX; id <= last_shader; id++) {
+ if (!sprog->ss[id])
+ continue;
if (sprog->ss[id]->sel->sinfo.samplers_used_mask) {
uint32_t mask = sprog->ss[id]->sel->sinfo.samplers_used_mask;
int nsamp = util_bitcount(sprog->ss[id]->sel->sinfo.samplers_used_mask);
@@ -1020,6 +1043,8 @@ static struct vrend_linked_shader_program *add_shader_program(struct vrend_conte
}
for (id = PIPE_SHADER_VERTEX; id <= last_shader; id++) {
+ if (!sprog->ss[id])
+ continue;
if (sprog->ss[id]->sel->sinfo.num_consts) {
sprog->const_locs[id] = calloc(sprog->ss[id]->sel->sinfo.num_consts, sizeof(uint32_t));
if (sprog->const_locs[id]) {
@@ -1047,6 +1072,8 @@ static struct vrend_linked_shader_program *add_shader_program(struct vrend_conte
}
for (id = PIPE_SHADER_VERTEX; id <= last_shader; id++) {
+ if (!sprog->ss[id])
+ continue;
if (sprog->ss[id]->sel->sinfo.num_ubos) {
const char *prefix = pipe_shader_to_prefix(id);
@@ -1077,6 +1104,8 @@ static struct vrend_linked_shader_program *lookup_shader_program(struct vrend_co
GLuint vs_id,
GLuint fs_id,
GLuint gs_id,
+ GLuint tcs_id,
+ GLuint tes_id,
bool dual_src)
{
struct vrend_linked_shader_program *ent;
@@ -1091,6 +1120,12 @@ static struct vrend_linked_shader_program *lookup_shader_program(struct vrend_co
if (ent->ss[PIPE_SHADER_GEOMETRY] &&
ent->ss[PIPE_SHADER_GEOMETRY]->id != gs_id)
continue;
+ if (ent->ss[PIPE_SHADER_TESS_CTRL] &&
+ ent->ss[PIPE_SHADER_TESS_CTRL]->id != tcs_id)
+ continue;
+ if (ent->ss[PIPE_SHADER_TESS_EVAL] &&
+ ent->ss[PIPE_SHADER_TESS_EVAL]->id != tes_id)
+ continue;
return ent;
}
return NULL;
@@ -1102,7 +1137,7 @@ static void vrend_destroy_program(struct vrend_linked_shader_program *ent)
glDeleteProgram(ent->id);
list_del(&ent->head);
- for (i = PIPE_SHADER_VERTEX; i <= PIPE_SHADER_GEOMETRY; i++) {
+ for (i = PIPE_SHADER_VERTEX; i <= PIPE_SHADER_TESS_EVAL; i++) {
if (ent->ss[i])
list_del(&ent->sl[i]);
free(ent->shadow_samp_mask_locs[i]);
@@ -2170,11 +2205,73 @@ static inline void vrend_fill_shader_key(struct vrend_context *ctx,
if (ctx->sub->shaders[PIPE_SHADER_GEOMETRY])
key->gs_present = true;
+ if (ctx->sub->shaders[PIPE_SHADER_TESS_CTRL])
+ key->tcs_present = true;
+ if (ctx->sub->shaders[PIPE_SHADER_TESS_EVAL])
+ key->tes_present = true;
+
+ int prev_type = -1;
- if ((type == PIPE_SHADER_GEOMETRY || type == PIPE_SHADER_FRAGMENT) && ctx->sub->shaders[PIPE_SHADER_VERTEX]) {
- key->prev_stage_pervertex_out = ctx->sub->shaders[PIPE_SHADER_VERTEX]->sinfo.has_pervertex_out;
- key->prev_stage_num_clip_out = ctx->sub->shaders[PIPE_SHADER_VERTEX]->sinfo.num_clip_out;
- key->prev_stage_num_cull_out = ctx->sub->shaders[PIPE_SHADER_VERTEX]->sinfo.num_cull_out;
+ switch (type) {
+ case PIPE_SHADER_GEOMETRY:
+ if (key->tcs_present || key->tes_present)
+ prev_type = PIPE_SHADER_TESS_EVAL;
+ else
+ prev_type = PIPE_SHADER_VERTEX;
+ break;
+ case PIPE_SHADER_FRAGMENT:
+ if (key->gs_present)
+ prev_type = PIPE_SHADER_GEOMETRY;
+ else if (key->tcs_present || key->tes_present)
+ prev_type = PIPE_SHADER_TESS_EVAL;
+ else
+ prev_type = PIPE_SHADER_VERTEX;
+ break;
+ case PIPE_SHADER_TESS_EVAL:
+ prev_type = PIPE_SHADER_TESS_CTRL;
+ break;
+ case PIPE_SHADER_TESS_CTRL:
+ prev_type = PIPE_SHADER_VERTEX;
+ break;
+ default:
+ break;
+ }
+ if (prev_type != -1 && ctx->sub->shaders[prev_type]) {
+ key->prev_stage_pervertex_out = ctx->sub->shaders[prev_type]->sinfo.has_pervertex_out;
+ key->prev_stage_num_clip_out = ctx->sub->shaders[prev_type]->sinfo.num_clip_out;
+ key->prev_stage_num_cull_out = ctx->sub->shaders[prev_type]->sinfo.num_cull_out;
+ key->num_indirect_generic_inputs = ctx->sub->shaders[prev_type]->sinfo.num_indirect_generic_outputs;
+ key->num_indirect_patch_inputs = ctx->sub->shaders[prev_type]->sinfo.num_indirect_patch_outputs;
+ }
+
+ int next_type = -1;
+ switch (type) {
+ case PIPE_SHADER_VERTEX:
+ if (key->tcs_present)
+ next_type = PIPE_SHADER_TESS_CTRL;
+ else if (key->gs_present)
+ next_type = PIPE_SHADER_GEOMETRY;
+ else
+ next_type = PIPE_SHADER_FRAGMENT;
+ break;
+ case PIPE_SHADER_TESS_CTRL:
+ next_type = PIPE_SHADER_TESS_EVAL;
+ break;
+ case PIPE_SHADER_GEOMETRY:
+ next_type = PIPE_SHADER_FRAGMENT;
+ break;
+ case PIPE_SHADER_TESS_EVAL:
+ if (key->gs_present)
+ next_type = PIPE_SHADER_GEOMETRY;
+ else
+ next_type = PIPE_SHADER_FRAGMENT;
+ default:
+ break;
+ }
+
+ if (next_type != -1 && ctx->sub->shaders[next_type]) {
+ key->num_indirect_generic_outputs = ctx->sub->shaders[next_type]->sinfo.num_indirect_generic_inputs;
+ key->num_indirect_patch_outputs = ctx->sub->shaders[next_type]->sinfo.num_indirect_patch_inputs;
}
}
@@ -2313,7 +2410,12 @@ int vrend_create_shader(struct vrend_context *ctx,
bool finished = false;
int ret;
- if (type > PIPE_SHADER_GEOMETRY)
+ if (type > PIPE_SHADER_TESS_EVAL)
+ return EINVAL;
+
+ if (!vrend_state.have_tessellation &&
+ (type == PIPE_SHADER_TESS_CTRL ||
+ type == PIPE_SHADER_TESS_EVAL))
return EINVAL;
if (offlen & VIRGL_OBJ_SHADER_OFFSET_CONT)
@@ -2440,7 +2542,7 @@ void vrend_bind_shader(struct vrend_context *ctx,
{
struct vrend_shader_selector *sel;
- if (type > PIPE_SHADER_GEOMETRY)
+ if (type > PIPE_SHADER_TESS_EVAL)
return;
if (handle == 0) {
@@ -2988,7 +3090,7 @@ void vrend_draw_vbo(struct vrend_context *ctx,
if (ctx->sub->shader_dirty) {
struct vrend_linked_shader_program *prog;
- bool fs_dirty, vs_dirty, gs_dirty;
+ bool fs_dirty, vs_dirty, gs_dirty, tcs_dirty, tes_dirty;
bool dual_src = util_blend_state_is_dual(&ctx->sub->blend_state, 0);
bool same_prog;
if (!ctx->sub->shaders[PIPE_SHADER_VERTEX] || !ctx->sub->shaders[PIPE_SHADER_FRAGMENT]) {
@@ -3000,10 +3102,16 @@ void vrend_draw_vbo(struct vrend_context *ctx,
vrend_shader_select(ctx, ctx->sub->shaders[PIPE_SHADER_VERTEX], &vs_dirty);
if (ctx->sub->shaders[PIPE_SHADER_GEOMETRY])
vrend_shader_select(ctx, ctx->sub->shaders[PIPE_SHADER_GEOMETRY], &gs_dirty);
+ if (ctx->sub->shaders[PIPE_SHADER_TESS_CTRL])
+ vrend_shader_select(ctx, ctx->sub->shaders[PIPE_SHADER_TESS_CTRL], &tcs_dirty);
+ if (ctx->sub->shaders[PIPE_SHADER_TESS_EVAL])
+ vrend_shader_select(ctx, ctx->sub->shaders[PIPE_SHADER_TESS_EVAL], &tes_dirty);
if (!ctx->sub->shaders[PIPE_SHADER_VERTEX]->current ||
!ctx->sub->shaders[PIPE_SHADER_FRAGMENT]->current ||
- (ctx->sub->shaders[PIPE_SHADER_GEOMETRY] && !ctx->sub->shaders[PIPE_SHADER_GEOMETRY]->current)) {
+ (ctx->sub->shaders[PIPE_SHADER_GEOMETRY] && !ctx->sub->shaders[PIPE_SHADER_GEOMETRY]->current) ||
+ (ctx->sub->shaders[PIPE_SHADER_TESS_CTRL] && !ctx->sub->shaders[PIPE_SHADER_TESS_CTRL]->current) ||
+ (ctx->sub->shaders[PIPE_SHADER_TESS_EVAL] && !ctx->sub->shaders[PIPE_SHADER_TESS_EVAL]->current)) {
fprintf(stderr, "failure to compile shader variants: %s\n", ctx->debug_name);
return;
}
@@ -3016,23 +3124,31 @@ void vrend_draw_vbo(struct vrend_context *ctx,
same_prog = false;
if (ctx->sub->prog && ctx->sub->prog->dual_src_linked != dual_src)
same_prog = false;
+ if (ctx->sub->shaders[PIPE_SHADER_TESS_CTRL] && ctx->sub->shaders[PIPE_SHADER_TESS_CTRL]->current->id != (GLuint)ctx->sub->prog_ids[PIPE_SHADER_TESS_CTRL])
+ same_prog = false;
+ if (ctx->sub->shaders[PIPE_SHADER_TESS_EVAL] && ctx->sub->shaders[PIPE_SHADER_TESS_EVAL]->current->id != (GLuint)ctx->sub->prog_ids[PIPE_SHADER_TESS_EVAL])
+ same_prog = false;
if (!same_prog) {
prog = lookup_shader_program(ctx,
ctx->sub->shaders[PIPE_SHADER_VERTEX]->current->id,
ctx->sub->shaders[PIPE_SHADER_FRAGMENT]->current->id,
ctx->sub->shaders[PIPE_SHADER_GEOMETRY] ? ctx->sub->shaders[PIPE_SHADER_GEOMETRY]->current->id : 0,
+ ctx->sub->shaders[PIPE_SHADER_TESS_CTRL] ? ctx->sub->shaders[PIPE_SHADER_TESS_CTRL]->current->id : 0,
+ ctx->sub->shaders[PIPE_SHADER_TESS_EVAL] ? ctx->sub->shaders[PIPE_SHADER_TESS_EVAL]->current->id : 0,
dual_src);
if (!prog) {
prog = add_shader_program(ctx,
ctx->sub->shaders[PIPE_SHADER_VERTEX]->current,
ctx->sub->shaders[PIPE_SHADER_FRAGMENT]->current,
- ctx->sub->shaders[PIPE_SHADER_GEOMETRY] ? ctx->sub->shaders[PIPE_SHADER_GEOMETRY]->current : NULL);
+ ctx->sub->shaders[PIPE_SHADER_GEOMETRY] ? ctx->sub->shaders[PIPE_SHADER_GEOMETRY]->current : NULL,
+ ctx->sub->shaders[PIPE_SHADER_TESS_CTRL] ? ctx->sub->shaders[PIPE_SHADER_TESS_CTRL]->current : NULL,
+ ctx->sub->shaders[PIPE_SHADER_TESS_EVAL] ? ctx->sub->shaders[PIPE_SHADER_TESS_EVAL]->current : NULL);
if (!prog)
return;
}
- ctx->sub->last_shader_idx = ctx->sub->shaders[PIPE_SHADER_GEOMETRY] ? PIPE_SHADER_GEOMETRY : PIPE_SHADER_FRAGMENT;
+ ctx->sub->last_shader_idx = ctx->sub->shaders[PIPE_SHADER_TESS_EVAL] ? PIPE_SHADER_TESS_EVAL : (ctx->sub->shaders[PIPE_SHADER_GEOMETRY] ? PIPE_SHADER_GEOMETRY : PIPE_SHADER_FRAGMENT);
} else
prog = ctx->sub->prog;
if (ctx->sub->prog != prog) {
@@ -3041,6 +3157,10 @@ void vrend_draw_vbo(struct vrend_context *ctx,
ctx->sub->prog_ids[PIPE_SHADER_FRAGMENT] = ctx->sub->shaders[PIPE_SHADER_FRAGMENT]->current->id;
if (ctx->sub->shaders[PIPE_SHADER_GEOMETRY])
ctx->sub->prog_ids[PIPE_SHADER_GEOMETRY] = ctx->sub->shaders[PIPE_SHADER_GEOMETRY]->current->id;
+ if (ctx->sub->shaders[PIPE_SHADER_TESS_CTRL])
+ ctx->sub->prog_ids[PIPE_SHADER_TESS_CTRL] = ctx->sub->shaders[PIPE_SHADER_TESS_CTRL]->current->id;
+ if (ctx->sub->shaders[PIPE_SHADER_TESS_EVAL])
+ ctx->sub->prog_ids[PIPE_SHADER_TESS_EVAL] = ctx->sub->shaders[PIPE_SHADER_TESS_EVAL]->current->id;
ctx->sub->prog = prog;
}
}
@@ -3131,6 +3251,9 @@ void vrend_draw_vbo(struct vrend_context *ctx,
else
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0);
+ if (info->vertices_per_patch && vrend_state.have_tessellation)
+ glPatchParameteri(GL_PATCH_VERTICES, info->vertices_per_patch);
+
/* set the vertex state up now on a delay */
if (!info->indexed) {
GLenum mode = info->mode;
@@ -4395,6 +4518,8 @@ static void vrend_destroy_sub_context(struct vrend_sub_context *sub)
vrend_shader_state_reference(&sub->shaders[PIPE_SHADER_VERTEX], NULL);
vrend_shader_state_reference(&sub->shaders[PIPE_SHADER_FRAGMENT], NULL);
vrend_shader_state_reference(&sub->shaders[PIPE_SHADER_GEOMETRY], NULL);
+ vrend_shader_state_reference(&sub->shaders[PIPE_SHADER_TESS_CTRL], NULL);
+ vrend_shader_state_reference(&sub->shaders[PIPE_SHADER_TESS_EVAL], NULL);
vrend_free_programs(sub);
for (i = 0; i < PIPE_SHADER_TYPES; i++) {
@@ -4446,6 +4571,8 @@ bool vrend_destroy_context(struct vrend_context *ctx)
vrend_set_num_sampler_views(ctx, PIPE_SHADER_VERTEX, 0, 0);
vrend_set_num_sampler_views(ctx, PIPE_SHADER_FRAGMENT, 0, 0);
vrend_set_num_sampler_views(ctx, PIPE_SHADER_GEOMETRY, 0, 0);
+ vrend_set_num_sampler_views(ctx, PIPE_SHADER_TESS_CTRL, 0, 0);
+ vrend_set_num_sampler_views(ctx, PIPE_SHADER_TESS_EVAL, 0, 0);
vrend_set_streamout_targets(ctx, 0, 0, NULL);
vrend_set_num_vbo(ctx, 0);
--
2.14.3
More information about the virglrenderer-devel
mailing list