diff options
author | Dave Airlie <airlied@redhat.com> | 2017-08-11 13:02:29 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2018-05-15 14:56:29 +1000 |
commit | eb1e49f989f1584d616932c82cc55b9a252d5c06 (patch) | |
tree | b188a77a077decd2c941b74bb5f4eeee685cd524 | |
parent | 5c3551cf1b6331218bb45af184f37e3b184d4a61 (diff) |
renderer: start adding some more TESS support
-rw-r--r-- | src/vrend_renderer.c | 100 | ||||
-rw-r--r-- | src/vrend_shader.c | 254 | ||||
-rw-r--r-- | src/vrend_shader.h | 2 |
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; |