summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2017-08-11 13:02:29 +1000
committerDave Airlie <airlied@redhat.com>2017-08-11 13:15:44 +1000
commite9643ef9d54a8b03f921850f6b284e9245ab05be (patch)
tree815d3d8263017b94a61c982b4ffdf789c1517858
parent9a2f52fff1aa63f79107b43ddf9d96d52b511227 (diff)
renderer: start adding some more TESS supportgl-4.1
-rw-r--r--src/vrend_renderer.c100
-rw-r--r--src/vrend_shader.c299
-rw-r--r--src/vrend_shader.h2
3 files changed, 332 insertions, 69 deletions
diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c
index 61727e8..a9a7b5e 100644
--- a/src/vrend_renderer.c
+++ b/src/vrend_renderer.c
@@ -454,6 +454,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;
};
@@ -810,7 +812,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];
@@ -826,7 +830,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) {
@@ -836,24 +842,35 @@ static struct vrend_linked_shader_program *add_shader_program(struct vrend_conte
vrend_patch_vertex_shader_interpolants(gs->glsl_prog,
&gs->sel->sinfo,
&fs->sel->sinfo, "gso", fs->key.flatshade);
+ else if (tes)
+ vrend_patch_vertex_shader_interpolants(tes->glsl_prog,
+ &tes->sel->sinfo,
+ &fs->sel->sinfo, "teo", fs->key.flatshade);
else
vrend_patch_vertex_shader_interpolants(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);
@@ -907,13 +924,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);
@@ -924,6 +947,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");
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);
@@ -966,6 +991,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]) {
@@ -993,6 +1020,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);
@@ -1019,7 +1048,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) {
@@ -1033,6 +1067,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;
@@ -1044,7 +1084,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]);
@@ -2060,6 +2100,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 && ctx->sub->shaders[PIPE_SHADER_VERTEX]) {
key->vs_has_pervertex = ctx->sub->shaders[PIPE_SHADER_VERTEX]->sinfo.num_pervertex_clip > 0;
@@ -2073,6 +2117,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;
};
@@ -2200,7 +2246,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)
@@ -2327,7 +2373,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) {
@@ -2790,7 +2836,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]) {
@@ -2802,10 +2848,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;
}
@@ -2816,23 +2868,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) {
@@ -2841,6 +2901,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;
}
}
@@ -2929,6 +2993,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;
@@ -4000,6 +4067,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++) {
@@ -4051,6 +4120,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);
@@ -6285,7 +6356,8 @@ void vrend_renderer_fill_caps(uint32_t set, uint32_t version,
(1 << PIPE_PRIM_LINE_STRIP_ADJACENCY) |
(1 << PIPE_PRIM_TRIANGLES_ADJACENCY) |
(1 << PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY);
-
+ if (caps->v1.glsl_level >= 400)
+ caps->v1.prim_mask |= (1 << PIPE_PRIM_PATCHES);
if (epoxy_has_gl_extension("GL_ARB_vertex_type_10f_11f_11f_rev")) {
int val = VIRGL_FORMAT_R11G11B10_FLOAT;
diff --git a/src/vrend_shader.c b/src/vrend_shader.c
index fca4114..61f6b5f 100644
--- a/src/vrend_shader.c
+++ b/src/vrend_shader.c
@@ -48,7 +48,7 @@ struct vrend_shader_io {
bool centroid;
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];
@@ -156,6 +156,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)
@@ -164,6 +170,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;
};
@@ -179,10 +187,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) {
@@ -319,7 +338,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:
@@ -410,20 +429,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) {
@@ -434,11 +457,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";
@@ -469,21 +494,35 @@ iter_declaration(struct tgsi_iterate_context *iter,
}
}
default:
- switch (iter->processor.Processor) {
- case TGSI_PROCESSOR_FRAGMENT:
- if (ctx->key->gs_present)
- name_prefix = "gso";
- else
- name_prefix = "vso";
- break;
- case TGSI_PROCESSOR_GEOMETRY:
- name_prefix = "vso";
- break;
- case TGSI_PROCESSOR_VERTEX:
- default:
- name_prefix = "in";
- break;
- }
+ switch (iter->processor.Processor) {
+ 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:
+ default:
+ name_prefix = "in";
+ break;
+ }
break;
}
@@ -496,6 +535,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);
}
@@ -526,12 +567,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;
@@ -558,6 +603,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";
@@ -606,17 +653,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:
@@ -648,22 +693,46 @@ 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)
color_offset = -1;
default:
- switch (iter->processor.Processor) {
- case TGSI_PROCESSOR_FRAGMENT:
- name_prefix = "fsout";
- break;
- case TGSI_PROCESSOR_GEOMETRY:
- name_prefix = "gso";
- break;
- case TGSI_PROCESSOR_VERTEX:
- name_prefix = "vso";
- break;
- default:
+ switch (iter->processor.Processor) {
+ case TGSI_PROCESSOR_FRAGMENT:
+ name_prefix = "fsout";
+ break;
+ case TGSI_PROCESSOR_VERTEX:
+ name_prefix = "vso";
+ break;
+ case TGSI_PROCESSOR_GEOMETRY:
+ name_prefix = "gso";
+ break;
+ case TGSI_PROCESSOR_TESS_CTRL:
+ name_prefix = "tco";
+ break;
+ case TGSI_PROCESSOR_TESS_EVAL:
+ name_prefix = "teo";
+ break;
+ default:
name_prefix = "out";
break;
}
@@ -679,6 +748,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
@@ -778,6 +849,12 @@ iter_declaration(struct tgsi_iterate_context *iter,
} 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";
@@ -826,6 +903,26 @@ iter_property(struct tgsi_iterate_context *iter,
if (prop->Property.PropertyName == TGSI_PROPERTY_GS_INVOCATIONS) {
ctx->gs_num_invocations = 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;
}
@@ -1084,10 +1181,13 @@ static int emit_clip_dist_movs(struct dump_ctx *ctx)
char buf[255];
int i;
char *sret;
+ 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;
@@ -1106,8 +1206,8 @@ static int emit_clip_dist_movs(struct dump_ctx *ctx)
default:
return EINVAL;
}
- snprintf(buf, 255, "gl_ClipDistance[%d] = clip_dist_temp[%d].%c;\n",
- i, clipidx, wm);
+ snprintf(buf, 255, "%sgl_ClipDistance[%d] = clip_dist_temp[%d].%c;\n",
+ prefix, i, clipidx, wm);
sret = add_str_to_glsl_main(ctx, buf);
if (!sret)
return ENOMEM;
@@ -1706,7 +1806,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;
@@ -1723,8 +1825,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";
@@ -1798,7 +1909,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) {
int idx;
@@ -2006,7 +2117,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),
@@ -2403,7 +2518,7 @@ iter_instruction(struct tgsi_iterate_context *iter,
ret = emit_clip_dist_movs(ctx);
if (ret)
return FALSE;
- if (!ctx->key->gs_present) {
+ if (!ctx->key->gs_present && !ctx->key->tes_present) {
ret = emit_prescale(ctx);
if (ret)
return FALSE;
@@ -2411,6 +2526,20 @@ iter_instruction(struct tgsi_iterate_context *iter,
} 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 (ctx->key->pstipple_tex) {
ret = emit_pstipple_pass(ctx);
@@ -2615,7 +2744,10 @@ prolog(struct tgsi_iterate_context *iter)
static char *emit_header(struct dump_ctx *ctx, char *glsl_hdr)
{
- 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)
@@ -2623,6 +2755,10 @@ static char *emit_header(struct dump_ctx *ctx, char *glsl_hdr)
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))
@@ -2728,6 +2864,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;
@@ -2778,7 +2927,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->inputs[i].interpolate, ctx->key->flatshade);
@@ -2789,12 +2940,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, "%sin vec4 %s%s;\n", prefix, 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++) {
snprintf(buf, 255, "out vec4 fsout_c%d;\n", i);
@@ -2809,13 +2975,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) %sout vec4 %s;\n", ctx->outputs[i].stream, prefix, ctx->outputs[i].glsl_name);
else
snprintf(buf, 255, "%sout vec4 %s;\n", prefix, ctx->outputs[i].glsl_name);
@@ -2888,6 +3064,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 f7f5dfc..aaee548 100644
--- a/src/vrend_shader.h
+++ b/src/vrend_shader.h
@@ -75,6 +75,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 vs_has_pervertex;
uint8_t vs_pervertex_num_clip;