summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2017-08-11 13:02:29 +1000
committerDave Airlie <airlied@redhat.com>2018-05-15 14:56:29 +1000
commiteb1e49f989f1584d616932c82cc55b9a252d5c06 (patch)
treeb188a77a077decd2c941b74bb5f4eeee685cd524
parent5c3551cf1b6331218bb45af184f37e3b184d4a61 (diff)
renderer: start adding some more TESS support
-rw-r--r--src/vrend_renderer.c100
-rw-r--r--src/vrend_shader.c254
-rw-r--r--src/vrend_shader.h2
3 files changed, 314 insertions, 42 deletions
diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c
index d30a5ed..1c72966 100644
--- a/src/vrend_renderer.c
+++ b/src/vrend_renderer.c
@@ -463,6 +463,8 @@ static inline const char *pipe_shader_to_prefix(int shader_type)
case PIPE_SHADER_VERTEX: return "vs";
case PIPE_SHADER_FRAGMENT: return "fs";
case PIPE_SHADER_GEOMETRY: return "gs";
+ case PIPE_SHADER_TESS_CTRL: return "tc";
+ case PIPE_SHADER_TESS_EVAL: return "te";
default:
return NULL;
};
@@ -869,7 +871,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];
@@ -885,7 +889,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) {
@@ -895,24 +901,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);
@@ -966,13 +983,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);
@@ -983,6 +1006,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);
@@ -1025,6 +1050,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]) {
@@ -1052,6 +1079,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);
@@ -1079,7 +1108,12 @@ static struct vrend_linked_shader_program *add_shader_program(struct vrend_conte
}
static struct vrend_linked_shader_program *lookup_shader_program(struct vrend_context *ctx,
- GLuint vs_id, GLuint fs_id, GLuint gs_id, bool dual_src)
+ GLuint vs_id,
+ GLuint fs_id,
+ GLuint gs_id,
+ GLuint tcs_id,
+ GLuint tes_id,
+ bool dual_src)
{
struct vrend_linked_shader_program *ent;
LIST_FOR_EACH_ENTRY(ent, &ctx->sub->programs, head) {
@@ -1093,6 +1127,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;
@@ -1104,7 +1144,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]);
@@ -2156,6 +2196,10 @@ 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;
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;
@@ -2170,6 +2214,8 @@ static inline int conv_shader_type(int type)
case PIPE_SHADER_VERTEX: return GL_VERTEX_SHADER;
case PIPE_SHADER_FRAGMENT: return GL_FRAGMENT_SHADER;
case PIPE_SHADER_GEOMETRY: return GL_GEOMETRY_SHADER;
+ case PIPE_SHADER_TESS_CTRL: return GL_TESS_CONTROL_SHADER;
+ case PIPE_SHADER_TESS_EVAL: return GL_TESS_EVALUATION_SHADER;
default:
return 0;
};
@@ -2297,7 +2343,7 @@ 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 (offlen & VIRGL_OBJ_SHADER_OFFSET_CONT)
@@ -2424,7 +2470,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) {
@@ -2974,7 +3020,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]) {
@@ -2986,10 +3032,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;
}
@@ -3000,23 +3052,31 @@ void vrend_draw_vbo(struct vrend_context *ctx,
same_prog = false;
if (ctx->sub->shaders[PIPE_SHADER_GEOMETRY] && ctx->sub->shaders[PIPE_SHADER_GEOMETRY]->current->id != ctx->sub->prog_ids[PIPE_SHADER_GEOMETRY])
same_prog = false;
+ if (ctx->sub->shaders[PIPE_SHADER_TESS_CTRL] && ctx->sub->shaders[PIPE_SHADER_TESS_CTRL]->current->id != 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 != 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) {
@@ -3025,6 +3085,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;
}
}
@@ -3115,6 +3179,9 @@ void vrend_draw_vbo(struct vrend_context *ctx,
else
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0);
+ if (info->vertices_per_patch)
+ glPatchParameteri(GL_PATCH_VERTICES, info->vertices_per_patch);
+
/* set the vertex state up now on a delay */
if (!info->indexed) {
GLenum mode = info->mode;
@@ -4346,6 +4413,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++) {
@@ -4397,6 +4466,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);
@@ -6660,6 +6731,8 @@ bool vrend_renderer_fill_caps_common(uint32_t set, uint32_t version,
(1 << PIPE_PRIM_TRIANGLES_ADJACENCY) |
(1 << PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY);
}
+ if (!vrend_state.use_gles && caps->v1.glsl_level >= 400)
+ caps->v1.prim_mask |= (1 << PIPE_PRIM_PATCHES);
/* Common limits for all backends. */
@@ -6962,7 +7035,6 @@ void vrend_renderer_fill_caps(uint32_t set, uint32_t version,
caps->v1.max_viewports = 1;
}
-
if (!fill_capset2)
return;
diff --git a/src/vrend_shader.c b/src/vrend_shader.c
index 78c929b..d4633be 100644
--- a/src/vrend_shader.c
+++ b/src/vrend_shader.c
@@ -51,7 +51,7 @@ struct vrend_shader_io {
bool invariant;
bool glsl_predefined_no_emit;
bool glsl_no_index;
- bool glsl_gl_in;
+ bool glsl_gl_block;
bool override_no_wm;
bool is_int;
char glsl_name[64];
@@ -159,6 +159,12 @@ struct dump_ctx {
bool uses_gpu_shader5;
bool write_mul_temp;
bool write_interp_temp;
+
+ int tcs_vertices_out;
+ int tes_prim_mode;
+ int tes_spacing;
+ int tes_vertex_order;
+ int tes_point_mode;
};
static inline const char *tgsi_proc_to_prefix(int shader_type)
@@ -167,6 +173,8 @@ static inline const char *tgsi_proc_to_prefix(int shader_type)
case TGSI_PROCESSOR_VERTEX: return "vs";
case TGSI_PROCESSOR_FRAGMENT: return "fs";
case TGSI_PROCESSOR_GEOMETRY: return "gs";
+ case TGSI_PROCESSOR_TESS_CTRL: return "tc";
+ case TGSI_PROCESSOR_TESS_EVAL: return "te";
default:
return NULL;
};
@@ -182,10 +190,21 @@ static inline const char *prim_to_name(int prim)
case PIPE_PRIM_TRIANGLES: return "triangles";
case PIPE_PRIM_TRIANGLE_STRIP: return "triangle_strip";
case PIPE_PRIM_TRIANGLES_ADJACENCY: return "triangles_adjacency";
+ case PIPE_PRIM_QUADS: return "quads";
default: return "UNKNOWN";
};
}
+static inline const char *prim_to_tes_name(int prim)
+{
+ switch (prim) {
+ case PIPE_PRIM_QUADS: return "quads";
+ case PIPE_PRIM_TRIANGLES: return "triangles";
+ case PIPE_PRIM_LINES: return "isolines";
+ default: return "UNKNOWN";
+ }
+}
+
static inline int gs_input_prim_to_size(int prim)
{
switch (prim) {
@@ -323,7 +342,7 @@ iter_declaration(struct tgsi_iterate_context *iter,
ctx->inputs[i].glsl_predefined_no_emit = false;
ctx->inputs[i].glsl_no_index = false;
ctx->inputs[i].override_no_wm = false;
- ctx->inputs[i].glsl_gl_in = false;
+ ctx->inputs[i].glsl_gl_block = false;
switch (ctx->inputs[i].name) {
case TGSI_SEMANTIC_COLOR:
@@ -414,20 +433,24 @@ iter_declaration(struct tgsi_iterate_context *iter,
break;
}
case TGSI_SEMANTIC_PSIZE:
- if (iter->processor.Processor == TGSI_PROCESSOR_GEOMETRY) {
+ if (iter->processor.Processor == TGSI_PROCESSOR_GEOMETRY ||
+ iter->processor.Processor == TGSI_PROCESSOR_TESS_CTRL ||
+ iter->processor.Processor == TGSI_PROCESSOR_TESS_EVAL) {
name_prefix = "gl_PointSize";
ctx->inputs[i].glsl_predefined_no_emit = true;
ctx->inputs[i].glsl_no_index = true;
ctx->inputs[i].override_no_wm = true;
- ctx->inputs[i].glsl_gl_in = true;
+ ctx->inputs[i].glsl_gl_block = true;
break;
}
case TGSI_SEMANTIC_CLIPDIST:
- if (iter->processor.Processor == TGSI_PROCESSOR_GEOMETRY) {
+ if (iter->processor.Processor == TGSI_PROCESSOR_GEOMETRY ||
+ iter->processor.Processor == TGSI_PROCESSOR_TESS_CTRL ||
+ iter->processor.Processor == TGSI_PROCESSOR_TESS_EVAL) {
name_prefix = "gl_ClipDistance";
ctx->inputs[i].glsl_predefined_no_emit = true;
ctx->inputs[i].glsl_no_index = true;
- ctx->inputs[i].glsl_gl_in = true;
+ ctx->inputs[i].glsl_gl_block = true;
ctx->num_in_clip_dist += 4;
break;
} else if (iter->processor.Processor == TGSI_PROCESSOR_FRAGMENT) {
@@ -438,11 +461,13 @@ iter_declaration(struct tgsi_iterate_context *iter,
break;
}
case TGSI_SEMANTIC_POSITION:
- if (iter->processor.Processor == TGSI_PROCESSOR_GEOMETRY) {
+ if (iter->processor.Processor == TGSI_PROCESSOR_GEOMETRY ||
+ iter->processor.Processor == TGSI_PROCESSOR_TESS_CTRL ||
+ iter->processor.Processor == TGSI_PROCESSOR_TESS_EVAL) {
name_prefix = "gl_Position";
ctx->inputs[i].glsl_predefined_no_emit = true;
ctx->inputs[i].glsl_no_index = true;
- ctx->inputs[i].glsl_gl_in = true;
+ ctx->inputs[i].glsl_gl_block = true;
break;
} else if (iter->processor.Processor == TGSI_PROCESSOR_FRAGMENT) {
name_prefix = "gl_FragCoord";
@@ -480,10 +505,24 @@ iter_declaration(struct tgsi_iterate_context *iter,
case TGSI_PROCESSOR_FRAGMENT:
if (ctx->key->gs_present)
name_prefix = "gso";
+ else if (ctx->key->tes_present)
+ name_prefix = "teo";
else
name_prefix = "vso";
break;
case TGSI_PROCESSOR_GEOMETRY:
+ if (ctx->key->tes_present)
+ name_prefix = "teo";
+ else
+ name_prefix = "vso";
+ break;
+ case TGSI_PROCESSOR_TESS_EVAL:
+ if (ctx->key->tcs_present)
+ name_prefix = "tco";
+ else
+ name_prefix = "vso";
+ break;
+ case TGSI_PROCESSOR_TESS_CTRL:
name_prefix = "vso";
break;
case TGSI_PROCESSOR_VERTEX:
@@ -503,6 +542,8 @@ iter_declaration(struct tgsi_iterate_context *iter,
snprintf(ctx->inputs[i].glsl_name, 64, "%s_c%d", name_prefix, ctx->inputs[i].sid);
else if (ctx->inputs[i].name == TGSI_SEMANTIC_GENERIC)
snprintf(ctx->inputs[i].glsl_name, 64, "%s_g%d", name_prefix, ctx->inputs[i].sid);
+ else if (ctx->inputs[i].name == TGSI_SEMANTIC_PATCH)
+ snprintf(ctx->inputs[i].glsl_name, 64, "%s_p%d", name_prefix, ctx->inputs[i].sid);
else
snprintf(ctx->inputs[i].glsl_name, 64, "%s_%d", name_prefix, ctx->inputs[i].first);
}
@@ -534,12 +575,16 @@ iter_declaration(struct tgsi_iterate_context *iter,
switch (ctx->outputs[i].name) {
case TGSI_SEMANTIC_POSITION:
if (iter->processor.Processor == TGSI_PROCESSOR_VERTEX ||
- iter->processor.Processor == TGSI_PROCESSOR_GEOMETRY) {
+ iter->processor.Processor == TGSI_PROCESSOR_GEOMETRY ||
+ iter->processor.Processor == TGSI_PROCESSOR_TESS_CTRL ||
+ iter->processor.Processor == TGSI_PROCESSOR_TESS_EVAL) {
if (ctx->outputs[i].first > 0)
fprintf(stderr,"Illegal position input\n");
name_prefix = "gl_Position";
ctx->outputs[i].glsl_predefined_no_emit = true;
ctx->outputs[i].glsl_no_index = true;
+ if (iter->processor.Processor == TGSI_PROCESSOR_TESS_CTRL)
+ ctx->outputs[i].glsl_gl_block = true;
} else if (iter->processor.Processor == TGSI_PROCESSOR_FRAGMENT) {
name_prefix = "gl_FragDepth";
ctx->outputs[i].glsl_predefined_no_emit = true;
@@ -566,6 +611,8 @@ iter_declaration(struct tgsi_iterate_context *iter,
if (iter->processor.Processor == TGSI_PROCESSOR_VERTEX &&
ctx->key->gs_present)
ctx->glsl_ver_required = 150;
+ if (iter->processor.Processor == TGSI_PROCESSOR_TESS_CTRL)
+ ctx->outputs[i].glsl_gl_block = true;
break;
case TGSI_SEMANTIC_CLIPVERTEX:
name_prefix = "gl_ClipVertex";
@@ -614,17 +661,15 @@ iter_declaration(struct tgsi_iterate_context *iter,
break;
}
case TGSI_SEMANTIC_PSIZE:
- if (iter->processor.Processor == TGSI_PROCESSOR_VERTEX) {
- ctx->outputs[i].glsl_predefined_no_emit = true;
- ctx->outputs[i].glsl_no_index = true;
- ctx->outputs[i].override_no_wm = true;
- name_prefix = "gl_PointSize";
- break;
- } else if (iter->processor.Processor == TGSI_PROCESSOR_GEOMETRY) {
+ if (iter->processor.Processor == TGSI_PROCESSOR_VERTEX ||
+ iter->processor.Processor == TGSI_PROCESSOR_GEOMETRY ||
+ iter->processor.Processor == TGSI_PROCESSOR_TESS_CTRL) {
ctx->outputs[i].glsl_predefined_no_emit = true;
ctx->outputs[i].glsl_no_index = true;
ctx->outputs[i].override_no_wm = true;
name_prefix = "gl_PointSize";
+ if (iter->processor.Processor == TGSI_PROCESSOR_TESS_CTRL)
+ ctx->outputs[i].glsl_gl_block = true;
break;
}
case TGSI_SEMANTIC_LAYER:
@@ -656,6 +701,24 @@ iter_declaration(struct tgsi_iterate_context *iter,
ctx->has_viewport_idx = true;
break;
}
+ case TGSI_SEMANTIC_TESSOUTER:
+ if (iter->processor.Processor == TGSI_PROCESSOR_TESS_CTRL) {
+ ctx->outputs[i].glsl_predefined_no_emit = true;
+ ctx->outputs[i].glsl_no_index = true;
+ ctx->outputs[i].override_no_wm = true;
+ name_prefix = "gl_TessLevelOuter";
+ break;
+ }
+
+ case TGSI_SEMANTIC_TESSINNER:
+ if (iter->processor.Processor == TGSI_PROCESSOR_TESS_CTRL) {
+ ctx->outputs[i].glsl_predefined_no_emit = true;
+ ctx->outputs[i].glsl_no_index = true;
+ ctx->outputs[i].override_no_wm = true;
+ name_prefix = "gl_TessLevelInner";
+ break;
+ }
+
case TGSI_SEMANTIC_GENERIC:
if (iter->processor.Processor == TGSI_PROCESSOR_VERTEX)
if (ctx->outputs[i].name == TGSI_SEMANTIC_GENERIC)
@@ -671,6 +734,12 @@ iter_declaration(struct tgsi_iterate_context *iter,
case TGSI_PROCESSOR_VERTEX:
name_prefix = "vso";
break;
+ case TGSI_PROCESSOR_TESS_CTRL:
+ name_prefix = "tco";
+ break;
+ case TGSI_PROCESSOR_TESS_EVAL:
+ name_prefix = "teo";
+ break;
default:
name_prefix = "out";
break;
@@ -687,6 +756,8 @@ iter_declaration(struct tgsi_iterate_context *iter,
snprintf(ctx->outputs[i].glsl_name, 64, "%s_c%d", name_prefix, ctx->outputs[i].sid);
else if (ctx->outputs[i].name == TGSI_SEMANTIC_BCOLOR)
snprintf(ctx->outputs[i].glsl_name, 64, "%s_bc%d", name_prefix, ctx->outputs[i].sid);
+ else if (ctx->outputs[i].name == TGSI_SEMANTIC_PATCH)
+ snprintf(ctx->outputs[i].glsl_name, 64, "%s_p%d", name_prefix, ctx->outputs[i].sid);
else if (ctx->outputs[i].name == TGSI_SEMANTIC_GENERIC)
snprintf(ctx->outputs[i].glsl_name, 64, "%s_g%d", name_prefix, ctx->outputs[i].sid);
else
@@ -780,6 +851,18 @@ iter_declaration(struct tgsi_iterate_context *iter,
name_prefix = "gl_PrimitiveID";
ctx->has_ints = true;
ctx->uses_gpu_shader5 = true;
+ } else if (decl->Semantic.Name == TGSI_SEMANTIC_TESSCOORD) {
+ name_prefix = "gl_TessCoord";
+ ctx->system_values[i].override_no_wm = false;
+ } else if (decl->Semantic.Name == TGSI_SEMANTIC_VERTICESIN) {
+ name_prefix = "gl_PatchVerticesIn";
+ ctx->system_values[i].override_no_wm = false;
+ } else if (decl->Semantic.Name == TGSI_SEMANTIC_TESSOUTER) {
+ name_prefix = "gl_TessLevelOuter";
+ ctx->system_values[i].override_no_wm = false;
+ } else if (decl->Semantic.Name == TGSI_SEMANTIC_TESSINNER) {
+ name_prefix = "gl_TessLevelInner";
+ ctx->system_values[i].override_no_wm = false;
} else {
fprintf(stderr, "unsupported system value %d\n", decl->Semantic.Name);
name_prefix = "unknown";
@@ -836,6 +919,26 @@ iter_property(struct tgsi_iterate_context *iter,
if (prop->Property.PropertyName == TGSI_PROPERTY_NUM_CULLDIST_ENABLED) {
ctx->num_cull_dist_prop = prop->u[0].Data;
}
+
+ if (prop->Property.PropertyName == TGSI_PROPERTY_TCS_VERTICES_OUT) {
+ ctx->tcs_vertices_out = prop->u[0].Data;
+ }
+
+ if (prop->Property.PropertyName == TGSI_PROPERTY_TES_PRIM_MODE) {
+ ctx->tes_prim_mode = prop->u[0].Data;
+ }
+
+ if (prop->Property.PropertyName == TGSI_PROPERTY_TES_SPACING) {
+ ctx->tes_spacing = prop->u[0].Data;
+ }
+
+ if (prop->Property.PropertyName == TGSI_PROPERTY_TES_VERTEX_ORDER_CW) {
+ ctx->tes_vertex_order = prop->u[0].Data;
+ }
+
+ if (prop->Property.PropertyName == TGSI_PROPERTY_TES_POINT_MODE) {
+ ctx->tes_point_mode = prop->u[0].Data;
+ }
return TRUE;
}
@@ -1099,9 +1202,13 @@ static int emit_clip_dist_movs(struct dump_ctx *ctx)
char *sret;
bool has_prop = (ctx->num_clip_dist_prop + ctx->num_cull_dist_prop) > 0;
int ndists;
+ const char *prefix="";
+
+ if (ctx->prog_type == PIPE_SHADER_TESS_CTRL)
+ prefix = "gl_out[gl_InvocationID].";
if (ctx->num_clip_dist == 0 && ctx->key->clip_plane_enable) {
for (i = 0; i < 8; i++) {
- snprintf(buf, 255, "gl_ClipDistance[%d] = dot(%s, clipp[%d]);\n", i, ctx->has_clipvertex ? "clipv_tmp" : "gl_Position", i);
+ snprintf(buf, 255, "%sgl_ClipDistance[%d] = dot(%s, clipp[%d]);\n", prefix, i, ctx->has_clipvertex ? "clipv_tmp" : "gl_Position", i);
sret = add_str_to_glsl_main(ctx, buf);
if (!sret)
return ENOMEM;
@@ -1129,7 +1236,7 @@ static int emit_clip_dist_movs(struct dump_ctx *ctx)
is_cull = true;
}
const char *clip_cull = is_cull ? "Cull" : "Clip";
- snprintf(buf, 255, "gl_%sDistance[%d] = clip_dist_temp[%d].%c;\n", clip_cull,
+ snprintf(buf, 255, "%sgl_%sDistance[%d] = clip_dist_temp[%d].%c;\n", prefix, clip_cull,
is_cull ? i - ctx->num_clip_dist_prop : i, clipidx, wm);
sret = add_str_to_glsl_main(ctx, buf);
if (!sret)
@@ -1165,7 +1272,7 @@ static int emit_buf(struct dump_ctx *ctx, const char *buf)
static int handle_vertex_proc_exit(struct dump_ctx *ctx)
{
- if (ctx->so && !ctx->key->gs_present) {
+ if (ctx->so && !ctx->key->gs_present && !ctx->key->tes_present) {
if (emit_so_movs(ctx))
return FALSE;
}
@@ -1792,7 +1899,9 @@ iter_instruction(struct tgsi_iterate_context *iter,
snprintf(dsts[i], 255, "clipv_tmp");
} else if (ctx->outputs[j].name == TGSI_SEMANTIC_CLIPDIST) {
snprintf(dsts[i], 255, "clip_dist_temp[%d]", ctx->outputs[j].sid);
- } else if (ctx->outputs[j].name == TGSI_SEMANTIC_SAMPLEMASK) {
+ } else if (ctx->outputs[j].name == TGSI_SEMANTIC_TESSOUTER ||
+ ctx->outputs[j].name == TGSI_SEMANTIC_TESSINNER ||
+ ctx->outputs[j].name == TGSI_SEMANTIC_SAMPLEMASK) {
int idx;
switch (dst->Register.WriteMask) {
case 0x1: idx = 0; break;
@@ -1809,8 +1918,17 @@ iter_instruction(struct tgsi_iterate_context *iter,
snprintf(dstconv, 6, "int");
}
} else {
- snprintf(dsts[i], 255, "%s%s", ctx->outputs[j].glsl_name, ctx->outputs[j].override_no_wm ? "" : writemask);
- dst_override_no_wm[i] = ctx->outputs[j].override_no_wm;
+ if (ctx->outputs[j].glsl_gl_block) {
+ snprintf(dsts[i], 255, "gl_out[%s].%s%s",
+ ctx->prog_type == TGSI_PROCESSOR_TESS_CTRL ? "gl_InvocationID" : "0",
+ ctx->outputs[j].glsl_name,
+ ctx->outputs[j].override_no_wm ? "" : writemask);
+ } else if (ctx->prog_type == TGSI_PROCESSOR_TESS_CTRL && ctx->outputs[j].name != TGSI_SEMANTIC_PATCH)
+ snprintf(dsts[i], 255, "%s[gl_InvocationID]%s", ctx->outputs[j].glsl_name, ctx->outputs[j].override_no_wm ? "" : writemask);
+ else {
+ snprintf(dsts[i], 255, "%s%s", ctx->outputs[j].glsl_name, ctx->outputs[j].override_no_wm ? "" : writemask);
+ dst_override_no_wm[i] = ctx->outputs[j].override_no_wm;
+ }
if (ctx->outputs[j].is_int) {
if (!strcmp(dtypeprefix, ""))
dtypeprefix = "floatBitsToInt";
@@ -1879,7 +1997,7 @@ iter_instruction(struct tgsi_iterate_context *iter,
if (ctx->inputs[j].first == src->Register.Index) {
if (ctx->key->color_two_side && ctx->inputs[j].name == TGSI_SEMANTIC_COLOR)
snprintf(srcs[i], 255, "%s(%s%s%d%s%s)", stypeprefix, prefix, "realcolor", ctx->inputs[j].sid, arrayname, swizzle);
- else if (ctx->inputs[j].glsl_gl_in) {
+ else if (ctx->inputs[j].glsl_gl_block) {
/* GS input clipdist requires a conversion */
if (ctx->inputs[j].name == TGSI_SEMANTIC_CLIPDIST) {
create_swizzled_clipdist(ctx, srcs[i], src, j, true, stypeprefix, prefix, arrayname);
@@ -2073,7 +2191,11 @@ iter_instruction(struct tgsi_iterate_context *iter,
ctx->system_values[j].name == TGSI_SEMANTIC_INVOCATIONID ||
ctx->system_values[j].name == TGSI_SEMANTIC_SAMPLEID)
snprintf(srcs[i], 255, "%s(vec4(intBitsToFloat(%s)))", stypeprefix, ctx->system_values[j].glsl_name);
- else if (ctx->system_values[j].name == TGSI_SEMANTIC_SAMPLEPOS) {
+ else if (ctx->system_values[j].name == TGSI_SEMANTIC_TESSCOORD ||
+ ctx->system_values[j].name == TGSI_SEMANTIC_TESSINNER ||
+ ctx->system_values[j].name == TGSI_SEMANTIC_TESSOUTER) {
+ snprintf(srcs[i], 255, "%s%s[%d]", prefix, ctx->system_values[j].glsl_name, src->Register.SwizzleX);
+ } else if (ctx->system_values[j].name == TGSI_SEMANTIC_SAMPLEPOS) {
snprintf(srcs[i], 255, "vec4(%s.%c, %s.%c, %s.%c, %s.%c)",
ctx->system_values[j].glsl_name, get_swiz_char(src->Register.SwizzleX),
ctx->system_values[j].glsl_name, get_swiz_char(src->Register.SwizzleY),
@@ -2402,6 +2524,21 @@ iter_instruction(struct tgsi_iterate_context *iter,
if (iter->processor.Processor == TGSI_PROCESSOR_VERTEX) {
if (handle_vertex_proc_exit(ctx) == FALSE)
return FALSE;
+ } else if (iter->processor.Processor == TGSI_PROCESSOR_GEOMETRY) {
+
+ } else if (iter->processor.Processor == TGSI_PROCESSOR_TESS_CTRL) {
+ ret = emit_clip_dist_movs(ctx);
+ if (ret)
+ return FALSE;
+ } else if (iter->processor.Processor == TGSI_PROCESSOR_TESS_EVAL) {
+ ret = emit_clip_dist_movs(ctx);
+ if (ret)
+ return FALSE;
+ if (!ctx->key->gs_present) {
+ ret = emit_prescale(ctx);
+ if (ret)
+ return FALSE;
+ }
} else if (iter->processor.Processor == TGSI_PROCESSOR_FRAGMENT) {
if (handle_fragment_proc_exit(ctx) == FALSE)
return FALSE;
@@ -2594,12 +2731,20 @@ static char *emit_header(struct dump_ctx *ctx, char *glsl_hdr)
STRCAT_WITH_RET(glsl_hdr, "precision highp float;\n");
STRCAT_WITH_RET(glsl_hdr, "precision highp int;\n");
} else {
- if (ctx->prog_type == TGSI_PROCESSOR_GEOMETRY || ctx->glsl_ver_required == 150)
+ if (ctx->prog_type == TGSI_PROCESSOR_GEOMETRY ||
+ ctx->prog_type == TGSI_PROCESSOR_TESS_EVAL ||
+ ctx->prog_type == TGSI_PROCESSOR_TESS_CTRL ||
+ ctx->glsl_ver_required == 150)
STRCAT_WITH_RET(glsl_hdr, "#version 150\n");
else if (ctx->glsl_ver_required == 140)
STRCAT_WITH_RET(glsl_hdr, "#version 140\n");
else
STRCAT_WITH_RET(glsl_hdr, "#version 130\n");
+
+ if (ctx->prog_type == TGSI_PROCESSOR_TESS_CTRL ||
+ ctx->prog_type == TGSI_PROCESSOR_TESS_EVAL)
+ STRCAT_WITH_RET(glsl_hdr, "#extension GL_ARB_tessellation_shader : require\n");
+
if (ctx->prog_type == TGSI_PROCESSOR_VERTEX && ctx->cfg->use_explicit_locations)
STRCAT_WITH_RET(glsl_hdr, "#extension GL_ARB_explicit_attrib_location : require\n");
if (ctx->prog_type == TGSI_PROCESSOR_FRAGMENT && fs_emit_layout(ctx))
@@ -2711,6 +2856,19 @@ static const char get_return_type_prefix(enum tgsi_return_type type)
return ' ';
}
+static const char *get_spacing_string(int spacing)
+{
+ switch (spacing) {
+ case PIPE_TESS_SPACING_FRACTIONAL_ODD:
+ return "fractional_odd_spacing";
+ case PIPE_TESS_SPACING_FRACTIONAL_EVEN:
+ return "fractional_even_spacing";
+ case PIPE_TESS_SPACING_EQUAL:
+ default:
+ return "equal_spacing";
+ }
+}
+
static char *emit_ios(struct dump_ctx *ctx, char *glsl_hdr)
{
int i;
@@ -2761,7 +2919,9 @@ static char *emit_ios(struct dump_ctx *ctx, char *glsl_hdr)
snprintf(buf, 255, "layout(location=%d) ", ctx->inputs[i].first);
STRCAT_WITH_RET(glsl_hdr, buf);
}
- if (ctx->prog_type == TGSI_PROCESSOR_FRAGMENT &&
+ if (ctx->prog_type == TGSI_PROCESSOR_TESS_EVAL && ctx->inputs[i].name == TGSI_SEMANTIC_PATCH)
+ prefix = "patch ";
+ else if (ctx->prog_type == TGSI_PROCESSOR_FRAGMENT &&
(ctx->inputs[i].name == TGSI_SEMANTIC_GENERIC ||
ctx->inputs[i].name == TGSI_SEMANTIC_COLOR)) {
prefix = get_interp_string(ctx->cfg, ctx->inputs[i].interpolate, ctx->key->flatshade);
@@ -2773,12 +2933,27 @@ static char *emit_ios(struct dump_ctx *ctx, char *glsl_hdr)
if (ctx->prog_type == TGSI_PROCESSOR_GEOMETRY) {
snprintf(postfix, 8, "[%d]", gs_input_prim_to_size(ctx->gs_in_prim));
+ } else if (ctx->prog_type == TGSI_PROCESSOR_TESS_CTRL ||
+ (ctx->prog_type == TGSI_PROCESSOR_TESS_EVAL && ctx->inputs[i].name != TGSI_SEMANTIC_PATCH)) {
+ snprintf(postfix, 8, "[]");
} else
postfix[0] = 0;
snprintf(buf, 255, "%s%sin vec4 %s%s;\n", prefix, auxprefix, ctx->inputs[i].glsl_name, postfix);
STRCAT_WITH_RET(glsl_hdr, buf);
}
}
+ if (ctx->prog_type == TGSI_PROCESSOR_TESS_CTRL) {
+ snprintf(buf, 255, "layout(vertices = %d) out;\n", ctx->tcs_vertices_out);
+ STRCAT_WITH_RET(glsl_hdr, buf);
+ }
+ if (ctx->prog_type == TGSI_PROCESSOR_TESS_EVAL) {
+ snprintf(buf, 255, "layout(%s, %s, %s%s) in;\n",
+ prim_to_tes_name(ctx->tes_prim_mode),
+ get_spacing_string(ctx->tes_spacing),
+ ctx->tes_vertex_order ? "cw" : "ccw",
+ ctx->tes_point_mode ? ", point_mode" : "");
+ STRCAT_WITH_RET(glsl_hdr, buf);
+ }
if (ctx->write_all_cbufs) {
for (i = 0; i < 8; i++) {
if (ctx->cfg->use_gles)
@@ -2796,13 +2971,23 @@ static char *emit_ios(struct dump_ctx *ctx, char *glsl_hdr)
bcolor_emitted[ctx->outputs[i].sid] = true;
}
if (!ctx->outputs[i].glsl_predefined_no_emit) {
- if ((ctx->prog_type == TGSI_PROCESSOR_VERTEX || ctx->prog_type == TGSI_PROCESSOR_GEOMETRY) && (ctx->outputs[i].name == TGSI_SEMANTIC_GENERIC || ctx->outputs[i].name == TGSI_SEMANTIC_COLOR || ctx->outputs[i].name == TGSI_SEMANTIC_BCOLOR)) {
+ if ((ctx->prog_type == TGSI_PROCESSOR_VERTEX ||
+ ctx->prog_type == TGSI_PROCESSOR_GEOMETRY ||
+ ctx->prog_type == TGSI_PROCESSOR_TESS_EVAL) &&
+ (ctx->outputs[i].name == TGSI_SEMANTIC_GENERIC ||
+ ctx->outputs[i].name == TGSI_SEMANTIC_COLOR ||
+ ctx->outputs[i].name == TGSI_SEMANTIC_BCOLOR)) {
ctx->num_interps++;
prefix = INTERP_PREFIX;
} else
prefix = "";
/* ugly leave spaces to patch interp in later */
- if (ctx->prog_type == TGSI_PROCESSOR_GEOMETRY && ctx->outputs[i].stream)
+ if (ctx->prog_type == TGSI_PROCESSOR_TESS_CTRL) {
+ if (ctx->outputs[i].name == TGSI_SEMANTIC_PATCH)
+ snprintf(buf, 255, "patch out vec4 %s;\n", ctx->outputs[i].glsl_name);
+ else
+ snprintf(buf, 255, "%sout vec4 %s[];\n", prefix, ctx->outputs[i].glsl_name);
+ } else if (ctx->prog_type == TGSI_PROCESSOR_GEOMETRY && ctx->outputs[i].stream)
snprintf(buf, 255, "layout (stream = %d) %s%sout vec4 %s;\n", ctx->outputs[i].stream, prefix, ctx->outputs[i].invariant ? "invariant " : "", ctx->outputs[i].glsl_name);
else
snprintf(buf, 255, "%s%sout vec4 %s;\n", prefix, ctx->outputs[i].invariant ? "invariant " : "", ctx->outputs[i].glsl_name);
@@ -2918,6 +3103,19 @@ static char *emit_ios(struct dump_ctx *ctx, char *glsl_hdr)
}
}
+ if (ctx->prog_type == TGSI_PROCESSOR_TESS_CTRL) {
+ if (ctx->num_clip_dist) {
+ snprintf(buf, 255, "out gl_PerVertex {\n vec4 gl_Position;\n float gl_PointSize;\n float gl_ClipDistance[%d];\n} gl_out[];\n", ctx->num_clip_dist ? ctx->num_clip_dist : 8);
+ STRCAT_WITH_RET(glsl_hdr, buf);
+ snprintf(buf, 255, "vec4 clip_dist_temp[2];\n");
+ STRCAT_WITH_RET(glsl_hdr, buf);
+ }
+ }
+ if (ctx->prog_type == TGSI_PROCESSOR_TESS_EVAL) {
+ snprintf(buf, 255, "uniform vec4 winsys_adjust;\n");
+ STRCAT_WITH_RET(glsl_hdr, buf);
+ }
+
if (ctx->so) {
char outtype[6] = {0};
for (i = 0; i < ctx->so->num_outputs; i++) {
diff --git a/src/vrend_shader.h b/src/vrend_shader.h
index 897d750..a4593c5 100644
--- a/src/vrend_shader.h
+++ b/src/vrend_shader.h
@@ -79,6 +79,8 @@ struct vrend_shader_key {
uint8_t alpha_test;
uint8_t clip_plane_enable;
bool gs_present;
+ bool tcs_present;
+ bool tes_present;
bool flatshade;
bool prev_stage_pervertex_out;
uint8_t prev_stage_num_clip_out;