diff options
author | Dave Airlie <airlied@redhat.com> | 2017-08-11 13:02:29 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2017-08-11 13:15:44 +1000 |
commit | e9643ef9d54a8b03f921850f6b284e9245ab05be (patch) | |
tree | 815d3d8263017b94a61c982b4ffdf789c1517858 | |
parent | 9a2f52fff1aa63f79107b43ddf9d96d52b511227 (diff) |
renderer: start adding some more TESS supportgl-4.1
-rw-r--r-- | src/vrend_renderer.c | 100 | ||||
-rw-r--r-- | src/vrend_shader.c | 299 | ||||
-rw-r--r-- | src/vrend_shader.h | 2 |
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; |