diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c index 70dccda9972..3b2b2d0306f 100644 --- a/src/gallium/auxiliary/draw/draw_context.c +++ b/src/gallium/auxiliary/draw/draw_context.c @@ -44,6 +44,7 @@ #include "draw_prim_assembler.h" #include "draw_vs.h" #include "draw_gs.h" +#include "draw_tess.h" #ifdef LLVM_AVAILABLE #include "gallivm/lp_bld_init.h" @@ -454,7 +455,9 @@ draw_set_mapped_constant_buffer(struct draw_context *draw, unsigned size ) { debug_assert(shader_type == PIPE_SHADER_VERTEX || - shader_type == PIPE_SHADER_GEOMETRY); + shader_type == PIPE_SHADER_GEOMETRY || + shader_type == PIPE_SHADER_TESS_CTRL || + shader_type == PIPE_SHADER_TESS_EVAL); debug_assert(slot < PIPE_MAX_CONSTANT_BUFFERS); draw_do_flush(draw, DRAW_FLUSH_PARAMETER_CHANGE); @@ -468,6 +471,14 @@ draw_set_mapped_constant_buffer(struct draw_context *draw, draw->pt.user.gs_constants[slot] = buffer; draw->pt.user.gs_constants_size[slot] = size; break; + case PIPE_SHADER_TESS_CTRL: + draw->pt.user.tcs_constants[slot] = buffer; + draw->pt.user.tcs_constants_size[slot] = size; + break; + case PIPE_SHADER_TESS_EVAL: + draw->pt.user.tes_constants[slot] = buffer; + draw->pt.user.tes_constants_size[slot] = size; + break; default: assert(0 && "invalid shader type in draw_set_mapped_constant_buffer"); } @@ -481,7 +492,9 @@ draw_set_mapped_shader_buffer(struct draw_context *draw, unsigned size ) { debug_assert(shader_type == PIPE_SHADER_VERTEX || - shader_type == PIPE_SHADER_GEOMETRY); + shader_type == PIPE_SHADER_GEOMETRY || + shader_type == PIPE_SHADER_TESS_CTRL || + shader_type == PIPE_SHADER_TESS_EVAL); debug_assert(slot < PIPE_MAX_SHADER_BUFFERS); draw_do_flush(draw, DRAW_FLUSH_PARAMETER_CHANGE); @@ -495,6 +508,14 @@ draw_set_mapped_shader_buffer(struct draw_context *draw, draw->pt.user.gs_ssbos[slot] = buffer; draw->pt.user.gs_ssbos_size[slot] = size; break; + case PIPE_SHADER_TESS_CTRL: + draw->pt.user.tcs_ssbos[slot] = buffer; + draw->pt.user.tcs_ssbos_size[slot] = size; + break; + case PIPE_SHADER_TESS_EVAL: + draw->pt.user.tes_ssbos[slot] = buffer; + draw->pt.user.tes_ssbos_size[slot] = size; + break; default: assert(0 && "invalid shader type in draw_set_mapped_shader_buffer"); } @@ -622,6 +643,8 @@ draw_get_shader_info(const struct draw_context *draw) if (draw->gs.geometry_shader) { return &draw->gs.geometry_shader->info; + } else if (draw->tes.tess_eval_shader) { + return &draw->tes.tess_eval_shader->info; } else { return &draw->vs.vertex_shader->info; } @@ -788,11 +811,22 @@ draw_texture_sampler(struct draw_context *draw, enum pipe_shader_type shader, struct tgsi_sampler *sampler) { - if (shader == PIPE_SHADER_VERTEX) { + switch (shader) { + case PIPE_SHADER_VERTEX: draw->vs.tgsi.sampler = sampler; - } else { - debug_assert(shader == PIPE_SHADER_GEOMETRY); + break; + case PIPE_SHADER_GEOMETRY: draw->gs.tgsi.sampler = sampler; + break; + case PIPE_SHADER_TESS_CTRL: + draw->tcs.tgsi.sampler = sampler; + break; + case PIPE_SHADER_TESS_EVAL: + draw->tes.tgsi.sampler = sampler; + break; + default: + assert(0); + break; } } @@ -806,11 +840,22 @@ draw_image(struct draw_context *draw, enum pipe_shader_type shader, struct tgsi_image *image) { - if (shader == PIPE_SHADER_VERTEX) { + switch (shader) { + case PIPE_SHADER_VERTEX: draw->vs.tgsi.image = image; - } else { - debug_assert(shader == PIPE_SHADER_GEOMETRY); + break; + case PIPE_SHADER_GEOMETRY: draw->gs.tgsi.image = image; + break; + case PIPE_SHADER_TESS_CTRL: + draw->tcs.tgsi.image = image; + break; + case PIPE_SHADER_TESS_EVAL: + draw->tes.tgsi.image = image; + break; + default: + assert(0); + break; } } @@ -824,11 +869,22 @@ draw_buffer(struct draw_context *draw, enum pipe_shader_type shader, struct tgsi_buffer *buffer) { - if (shader == PIPE_SHADER_VERTEX) { + switch (shader) { + case PIPE_SHADER_VERTEX: draw->vs.tgsi.buffer = buffer; - } else { - debug_assert(shader == PIPE_SHADER_GEOMETRY); + break; + case PIPE_SHADER_GEOMETRY: draw->gs.tgsi.buffer = buffer; + break; + case PIPE_SHADER_TESS_CTRL: + draw->tcs.tgsi.buffer = buffer; + break; + case PIPE_SHADER_TESS_EVAL: + draw->tes.tgsi.buffer = buffer; + break; + default: + assert(0); + break; } } @@ -905,6 +961,8 @@ draw_current_shader_position_output(const struct draw_context *draw) { if (draw->gs.geometry_shader) return draw->gs.position_output; + if (draw->tes.tess_eval_shader) + return draw->tes.position_output; return draw->vs.position_output; } @@ -918,6 +976,8 @@ draw_current_shader_viewport_index_output(const struct draw_context *draw) { if (draw->gs.geometry_shader) return draw->gs.geometry_shader->viewport_index_output; + else if (draw->tes.tess_eval_shader) + return draw->tes.tess_eval_shader->viewport_index_output; return draw->vs.vertex_shader->viewport_index_output; } @@ -945,6 +1005,8 @@ draw_current_shader_clipvertex_output(const struct draw_context *draw) { if (draw->gs.geometry_shader) return draw->gs.position_output; + if (draw->tes.tess_eval_shader) + return draw->tes.position_output; return draw->vs.clipvertex_output; } @@ -954,6 +1016,8 @@ draw_current_shader_ccdistance_output(const struct draw_context *draw, int index debug_assert(index < PIPE_MAX_CLIP_OR_CULL_DISTANCE_ELEMENT_COUNT); if (draw->gs.geometry_shader) return draw->gs.geometry_shader->ccdistance_output[index]; + if (draw->tes.tess_eval_shader) + return draw->tes.tess_eval_shader->ccdistance_output[index]; return draw->vs.ccdistance_output[index]; } @@ -963,6 +1027,8 @@ draw_current_shader_num_written_clipdistances(const struct draw_context *draw) { if (draw->gs.geometry_shader) return draw->gs.geometry_shader->info.num_written_clipdistance; + if (draw->tes.tess_eval_shader) + return draw->tes.tess_eval_shader->info.num_written_clipdistance; return draw->vs.vertex_shader->info.num_written_clipdistance; } @@ -971,6 +1037,8 @@ draw_current_shader_num_written_culldistances(const struct draw_context *draw) { if (draw->gs.geometry_shader) return draw->gs.geometry_shader->info.num_written_culldistance; + if (draw->tes.tess_eval_shader) + return draw->tes.tess_eval_shader->info.num_written_culldistance; return draw->vs.vertex_shader->info.num_written_culldistance; } @@ -1168,6 +1236,8 @@ draw_get_shader_param(enum pipe_shader_type shader, enum pipe_shader_cap param) switch(shader) { case PIPE_SHADER_VERTEX: case PIPE_SHADER_GEOMETRY: + case PIPE_SHADER_TESS_CTRL: + case PIPE_SHADER_TESS_EVAL: return gallivm_get_shader_param(param); default: return 0; @@ -1250,3 +1320,14 @@ draw_will_inject_frontface(const struct draw_context *draw) (rast->fill_front != PIPE_POLYGON_MODE_FILL || rast->fill_back != PIPE_POLYGON_MODE_FILL)); } + +void +draw_set_tess_state(struct draw_context *draw, + const float default_outer_level[4], + const float default_inner_level[2]) +{ + for (unsigned i = 0; i < 4; i++) + draw->default_outer_tess_level[i] = default_outer_level[i]; + for (unsigned i = 0; i < 2; i++) + draw->default_inner_tess_level[i] = default_inner_level[i]; +} diff --git a/src/gallium/auxiliary/draw/draw_context.h b/src/gallium/auxiliary/draw/draw_context.h index 5ad26f1cf48..659b81fd0be 100644 --- a/src/gallium/auxiliary/draw/draw_context.h +++ b/src/gallium/auxiliary/draw/draw_context.h @@ -45,6 +45,8 @@ struct draw_context; struct draw_stage; struct draw_vertex_shader; struct draw_geometry_shader; +struct draw_tess_ctrl_shader; +struct draw_tess_eval_shader; struct draw_fragment_shader; struct tgsi_sampler; struct tgsi_image; @@ -265,6 +267,9 @@ void draw_bind_tess_eval_shader(struct draw_context *draw, struct draw_tess_eval_shader *dvs); void draw_delete_tess_eval_shader(struct draw_context *draw, struct draw_tess_eval_shader *dvs); +void draw_set_tess_state(struct draw_context *draw, + const float default_outer_level[4], + const float default_inner_level[2]); /* * Vertex data functions diff --git a/src/gallium/auxiliary/draw/draw_gs_tmp.h b/src/gallium/auxiliary/draw/draw_gs_tmp.h index bf276d38224..5a5b9e22ab3 100644 --- a/src/gallium/auxiliary/draw/draw_gs_tmp.h +++ b/src/gallium/auxiliary/draw/draw_gs_tmp.h @@ -12,7 +12,6 @@ const boolean quads_flatshade_last = FALSE; \ const boolean last_vertex_last = !gs->draw->rasterizer->flatshade_first; \ do { \ - debug_assert(input_prims->primitive_count == 1); \ switch (prim) { \ case PIPE_PRIM_QUADS: \ case PIPE_PRIM_QUAD_STRIP: \ diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c index e7cf576cbd1..3cfed5e65d8 100644 --- a/src/gallium/auxiliary/draw/draw_llvm.c +++ b/src/gallium/auxiliary/draw/draw_llvm.c @@ -2412,18 +2412,24 @@ draw_llvm_set_mapped_texture(struct draw_context *draw, unsigned j; struct draw_jit_texture *jit_tex; - assert(shader_stage == PIPE_SHADER_VERTEX || - shader_stage == PIPE_SHADER_GEOMETRY); - - if (shader_stage == PIPE_SHADER_VERTEX) { + switch (shader_stage) { + case PIPE_SHADER_VERTEX: assert(sview_idx < ARRAY_SIZE(draw->llvm->jit_context.textures)); - jit_tex = &draw->llvm->jit_context.textures[sview_idx]; - } else if (shader_stage == PIPE_SHADER_GEOMETRY) { + break; + case PIPE_SHADER_GEOMETRY: assert(sview_idx < ARRAY_SIZE(draw->llvm->gs_jit_context.textures)); - jit_tex = &draw->llvm->gs_jit_context.textures[sview_idx]; - } else { + break; + case PIPE_SHADER_TESS_CTRL: + assert(sview_idx < ARRAY_SIZE(draw->llvm->tcs_jit_context.textures)); + jit_tex = &draw->llvm->tcs_jit_context.textures[sview_idx]; + break; + case PIPE_SHADER_TESS_EVAL: + assert(sview_idx < ARRAY_SIZE(draw->llvm->tes_jit_context.textures)); + jit_tex = &draw->llvm->tes_jit_context.textures[sview_idx]; + break; + default: assert(0); return; } @@ -2453,18 +2459,24 @@ draw_llvm_set_mapped_image(struct draw_context *draw, { struct draw_jit_image *jit_image; - assert(shader_stage == PIPE_SHADER_VERTEX || - shader_stage == PIPE_SHADER_GEOMETRY); - - if (shader_stage == PIPE_SHADER_VERTEX) { + switch (shader_stage) { + case PIPE_SHADER_VERTEX: assert(idx < ARRAY_SIZE(draw->llvm->jit_context.images)); - jit_image = &draw->llvm->jit_context.images[idx]; - } else if (shader_stage == PIPE_SHADER_GEOMETRY) { + break; + case PIPE_SHADER_GEOMETRY: assert(idx < ARRAY_SIZE(draw->llvm->gs_jit_context.images)); - jit_image = &draw->llvm->gs_jit_context.images[idx]; - } else { + break; + case PIPE_SHADER_TESS_CTRL: + assert(idx < ARRAY_SIZE(draw->llvm->tcs_jit_context.images)); + jit_image = &draw->llvm->tcs_jit_context.images[idx]; + break; + case PIPE_SHADER_TESS_EVAL: + assert(idx < ARRAY_SIZE(draw->llvm->tes_jit_context.images)); + jit_image = &draw->llvm->tes_jit_context.images[idx]; + break; + default: assert(0); return; } @@ -2485,7 +2497,8 @@ draw_llvm_set_sampler_state(struct draw_context *draw, { unsigned i; - if (shader_type == PIPE_SHADER_VERTEX) { + switch (shader_type) { + case PIPE_SHADER_VERTEX: for (i = 0; i < draw->num_samplers[PIPE_SHADER_VERTEX]; i++) { struct draw_jit_sampler *jit_sam = &draw->llvm->jit_context.samplers[i]; @@ -2498,7 +2511,8 @@ draw_llvm_set_sampler_state(struct draw_context *draw, COPY_4V(jit_sam->border_color, s->border_color.f); } } - } else if (shader_type == PIPE_SHADER_GEOMETRY) { + break; + case PIPE_SHADER_GEOMETRY: for (i = 0; i < draw->num_samplers[PIPE_SHADER_GEOMETRY]; i++) { struct draw_jit_sampler *jit_sam = &draw->llvm->gs_jit_context.samplers[i]; @@ -2511,6 +2525,38 @@ draw_llvm_set_sampler_state(struct draw_context *draw, COPY_4V(jit_sam->border_color, s->border_color.f); } } + break; + case PIPE_SHADER_TESS_CTRL: + for (i = 0; i < draw->num_samplers[PIPE_SHADER_TESS_CTRL]; i++) { + struct draw_jit_sampler *jit_sam = &draw->llvm->tcs_jit_context.samplers[i]; + + if (draw->samplers[PIPE_SHADER_TESS_CTRL][i]) { + const struct pipe_sampler_state *s + = draw->samplers[PIPE_SHADER_TESS_CTRL][i]; + jit_sam->min_lod = s->min_lod; + jit_sam->max_lod = s->max_lod; + jit_sam->lod_bias = s->lod_bias; + COPY_4V(jit_sam->border_color, s->border_color.f); + } + } + break; + case PIPE_SHADER_TESS_EVAL: + for (i = 0; i < draw->num_samplers[PIPE_SHADER_TESS_EVAL]; i++) { + struct draw_jit_sampler *jit_sam = &draw->llvm->tes_jit_context.samplers[i]; + + if (draw->samplers[PIPE_SHADER_TESS_EVAL][i]) { + const struct pipe_sampler_state *s + = draw->samplers[PIPE_SHADER_TESS_EVAL][i]; + jit_sam->min_lod = s->min_lod; + jit_sam->max_lod = s->max_lod; + jit_sam->lod_bias = s->lod_bias; + COPY_4V(jit_sam->border_color, s->border_color.f); + } + } + break; + default: + assert(0); + break; } } diff --git a/src/gallium/auxiliary/draw/draw_prim_assembler.c b/src/gallium/auxiliary/draw/draw_prim_assembler.c index 7ff705a91a5..c0bc145f38b 100644 --- a/src/gallium/auxiliary/draw/draw_prim_assembler.c +++ b/src/gallium/auxiliary/draw/draw_prim_assembler.c @@ -29,7 +29,7 @@ #include "draw_fs.h" #include "draw_gs.h" - +#include "draw_tess.h" #include "util/u_debug.h" #include "util/u_memory.h" #include "util/u_prim.h" @@ -59,8 +59,14 @@ needs_primid(const struct draw_context *draw) { const struct draw_fragment_shader *fs = draw->fs.fragment_shader; const struct draw_geometry_shader *gs = draw->gs.geometry_shader; + const struct draw_tess_eval_shader *tes = draw->tes.tess_eval_shader; if (fs && fs->info.uses_primid) { - return !gs || !gs->info.uses_primid; + if (gs) + return !gs->info.uses_primid; + else if (tes) + return !tes->info.uses_primid; + else + return TRUE; } return FALSE; } diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c index 24ac0542726..986f87e0152 100644 --- a/src/gallium/auxiliary/draw/draw_pt.c +++ b/src/gallium/auxiliary/draw/draw_pt.c @@ -32,6 +32,7 @@ #include "draw/draw_context.h" #include "draw/draw_gs.h" +#include "draw/draw_tess.h" #include "draw/draw_private.h" #include "draw/draw_pt.h" #include "draw/draw_vbuf.h" @@ -66,16 +67,24 @@ draw_pt_arrays(struct draw_context *draw, */ { unsigned first, incr; - draw_pt_split_prim(prim, &first, &incr); + + if (prim == PIPE_PRIM_PATCHES) { + first = draw->pt.vertices_per_patch; + incr = draw->pt.vertices_per_patch; + } else + draw_pt_split_prim(prim, &first, &incr); count = draw_pt_trim_count(count, first, incr); if (count < first) return TRUE; } if (!draw->force_passthrough) { - unsigned gs_out_prim = (draw->gs.geometry_shader ? - draw->gs.geometry_shader->output_primitive : - prim); + unsigned out_prim = prim; + + if (draw->gs.geometry_shader) + out_prim = draw->gs.geometry_shader->output_primitive; + else if (draw->tes.tess_eval_shader) + out_prim = get_tes_output_prim(draw->tes.tess_eval_shader); if (!draw->render) { opt |= PT_PIPELINE; @@ -83,7 +92,7 @@ draw_pt_arrays(struct draw_context *draw, if (draw_need_pipeline(draw, draw->rasterizer, - gs_out_prim)) { + out_prim)) { opt |= PT_PIPELINE; } @@ -487,6 +496,8 @@ draw_vbo(struct draw_context *draw, draw->pt.user.eltSize = info->index_size ? draw->pt.user.eltSizeIB : 0; draw->pt.user.drawid = info->drawid; + draw->pt.vertices_per_patch = info->vertices_per_patch; + if (0) debug_printf("draw_vbo(mode=%u start=%u count=%u):\n", info->mode, info->start, count); diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c index 3a75a00c363..f9db2928582 100644 --- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c +++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c @@ -30,6 +30,7 @@ #include "util/u_prim.h" #include "draw/draw_context.h" #include "draw/draw_gs.h" +#include "draw/draw_tess.h" #include "draw/draw_vbuf.h" #include "draw/draw_vertex.h" #include "draw/draw_pt.h" @@ -138,6 +139,146 @@ llvm_middle_end_prepare_gs(struct llvm_middle_end *fpme) gs->current_variant = variant; } +static void +llvm_middle_end_prepare_tcs(struct llvm_middle_end *fpme) +{ + struct draw_context *draw = fpme->draw; + struct draw_llvm *llvm = fpme->llvm; + struct draw_tess_ctrl_shader *tcs = draw->tcs.tess_ctrl_shader; + struct draw_tcs_llvm_variant_key *key; + struct draw_tcs_llvm_variant *variant = NULL; + struct draw_tcs_llvm_variant_list_item *li; + struct llvm_tess_ctrl_shader *shader = llvm_tess_ctrl_shader(tcs); + char store[DRAW_TCS_LLVM_MAX_VARIANT_KEY_SIZE]; + unsigned i; + + key = draw_tcs_llvm_make_variant_key(llvm, store); + + /* Search shader's list of variants for the key */ + li = first_elem(&shader->variants); + while (!at_end(&shader->variants, li)) { + if (memcmp(&li->base->key, key, shader->variant_key_size) == 0) { + variant = li->base; + break; + } + li = next_elem(li); + } + + if (variant) { + /* found the variant, move to head of global list (for LRU) */ + move_to_head(&llvm->tcs_variants_list, &variant->list_item_global); + } + else { + /* Need to create new variant */ + + /* First check if we've created too many variants. If so, free + * 3.125% of the LRU to avoid using too much memory. + */ + if (llvm->nr_tcs_variants >= DRAW_MAX_SHADER_VARIANTS) { + if (gallivm_debug & GALLIVM_DEBUG_PERF) { + debug_printf("Evicting TCS: %u tcs variants,\t%u total variants\n", + shader->variants_cached, llvm->nr_tcs_variants); + } + + /* + * XXX: should we flush here ? + */ + for (i = 0; i < DRAW_MAX_SHADER_VARIANTS / 32; i++) { + struct draw_tcs_llvm_variant_list_item *item; + if (is_empty_list(&llvm->tcs_variants_list)) { + break; + } + item = last_elem(&llvm->tcs_variants_list); + assert(item); + assert(item->base); + draw_tcs_llvm_destroy_variant(item->base); + } + } + + variant = draw_tcs_llvm_create_variant(llvm, 0, key); + + if (variant) { + insert_at_head(&shader->variants, &variant->list_item_local); + insert_at_head(&llvm->tcs_variants_list, + &variant->list_item_global); + llvm->nr_tcs_variants++; + shader->variants_cached++; + } + } + + tcs->current_variant = variant; +} + +static void +llvm_middle_end_prepare_tes(struct llvm_middle_end *fpme) +{ + struct draw_context *draw = fpme->draw; + struct draw_llvm *llvm = fpme->llvm; + struct draw_tess_eval_shader *tes = draw->tes.tess_eval_shader; + struct draw_tes_llvm_variant_key *key; + struct draw_tes_llvm_variant *variant = NULL; + struct draw_tes_llvm_variant_list_item *li; + struct llvm_tess_eval_shader *shader = llvm_tess_eval_shader(tes); + char store[DRAW_TES_LLVM_MAX_VARIANT_KEY_SIZE]; + unsigned i; + + key = draw_tes_llvm_make_variant_key(llvm, store); + + /* Search shader's list of variants for the key */ + li = first_elem(&shader->variants); + while (!at_end(&shader->variants, li)) { + if (memcmp(&li->base->key, key, shader->variant_key_size) == 0) { + variant = li->base; + break; + } + li = next_elem(li); + } + + if (variant) { + /* found the variant, move to head of global list (for LRU) */ + move_to_head(&llvm->tes_variants_list, &variant->list_item_global); + } + else { + /* Need to create new variant */ + + /* First check if we've created too many variants. If so, free + * 3.125% of the LRU to avoid using too much memory. + */ + if (llvm->nr_tes_variants >= DRAW_MAX_SHADER_VARIANTS) { + if (gallivm_debug & GALLIVM_DEBUG_PERF) { + debug_printf("Evicting TES: %u tes variants,\t%u total variants\n", + shader->variants_cached, llvm->nr_tes_variants); + } + + /* + * XXX: should we flush here ? + */ + for (i = 0; i < DRAW_MAX_SHADER_VARIANTS / 32; i++) { + struct draw_tes_llvm_variant_list_item *item; + if (is_empty_list(&llvm->tes_variants_list)) { + break; + } + item = last_elem(&llvm->tes_variants_list); + assert(item); + assert(item->base); + draw_tes_llvm_destroy_variant(item->base); + } + } + + variant = draw_tes_llvm_create_variant(llvm, tes->info.num_outputs, key); + + if (variant) { + insert_at_head(&shader->variants, &variant->list_item_local); + insert_at_head(&llvm->tes_variants_list, + &variant->list_item_global); + llvm->nr_tes_variants++; + shader->variants_cached++; + } + } + + tes->current_variant = variant; +} + /** * Prepare/validate middle part of the vertex pipeline. * NOTE: if you change this function, also look at the non-LLVM @@ -154,7 +295,9 @@ llvm_middle_end_prepare( struct draw_pt_middle_end *middle, struct draw_llvm *llvm = fpme->llvm; struct draw_vertex_shader *vs = draw->vs.vertex_shader; struct draw_geometry_shader *gs = draw->gs.geometry_shader; - const unsigned out_prim = gs ? gs->output_primitive : + struct draw_tess_ctrl_shader *tcs = draw->tcs.tess_ctrl_shader; + struct draw_tess_eval_shader *tes = draw->tes.tess_eval_shader; + const unsigned out_prim = gs ? gs->output_primitive : tes ? get_tes_output_prim(tes) : u_assembled_prim(in_prim); unsigned point_clip = draw->rasterizer->fill_front == PIPE_POLYGON_MODE_POINT || out_prim == PIPE_PRIM_POINTS; @@ -270,6 +413,12 @@ llvm_middle_end_prepare( struct draw_pt_middle_end *middle, if (gs) { llvm_middle_end_prepare_gs(fpme); } + if (tcs) { + llvm_middle_end_prepare_tcs(fpme); + } + if (tes) { + llvm_middle_end_prepare_tes(fpme); + } } @@ -329,6 +478,42 @@ llvm_middle_end_bind_parameters(struct draw_pt_middle_end *middle) } } + for (i = 0; i < ARRAY_SIZE(llvm->tcs_jit_context.constants); ++i) { + int num_consts = + DIV_ROUND_UP(draw->pt.user.tcs_constants_size[i], (sizeof(float) * 4)); + llvm->tcs_jit_context.constants[i] = draw->pt.user.tcs_constants[i]; + llvm->tcs_jit_context.num_constants[i] = num_consts; + if (num_consts == 0) { + llvm->tcs_jit_context.constants[i] = fake_const_buf; + } + } + for (i = 0; i < ARRAY_SIZE(llvm->tcs_jit_context.ssbos); ++i) { + int num_ssbos = draw->pt.user.tcs_ssbos_size[i]; + llvm->tcs_jit_context.ssbos[i] = draw->pt.user.tcs_ssbos[i]; + llvm->tcs_jit_context.num_ssbos[i] = num_ssbos; + if (num_ssbos == 0) { + llvm->tcs_jit_context.ssbos[i] = (const uint32_t *)fake_const_buf; + } + } + + for (i = 0; i < ARRAY_SIZE(llvm->tes_jit_context.constants); ++i) { + int num_consts = + DIV_ROUND_UP(draw->pt.user.tes_constants_size[i], (sizeof(float) * 4)); + llvm->tes_jit_context.constants[i] = draw->pt.user.tes_constants[i]; + llvm->tes_jit_context.num_constants[i] = num_consts; + if (num_consts == 0) { + llvm->tes_jit_context.constants[i] = fake_const_buf; + } + } + for (i = 0; i < ARRAY_SIZE(llvm->tes_jit_context.ssbos); ++i) { + int num_ssbos = draw->pt.user.tes_ssbos_size[i]; + llvm->tes_jit_context.ssbos[i] = draw->pt.user.tes_ssbos[i]; + llvm->tes_jit_context.num_ssbos[i] = num_ssbos; + if (num_ssbos == 0) { + llvm->tes_jit_context.ssbos[i] = (const uint32_t *)fake_const_buf; + } + } + llvm->jit_context.planes = (float (*)[DRAW_TOTAL_CLIP_PLANES][4]) draw->pt.user.planes[0]; llvm->gs_jit_context.planes = @@ -377,8 +562,14 @@ llvm_pipeline_generic(struct draw_pt_middle_end *middle, struct llvm_middle_end *fpme = llvm_middle_end(middle); struct draw_context *draw = fpme->draw; struct draw_geometry_shader *gshader = draw->gs.geometry_shader; + struct draw_tess_ctrl_shader *tcs_shader = draw->tcs.tess_ctrl_shader; + struct draw_tess_eval_shader *tes_shader = draw->tes.tess_eval_shader; + struct draw_prim_info tcs_prim_info; + struct draw_prim_info tes_prim_info; struct draw_prim_info gs_prim_info[TGSI_MAX_VERTEX_STREAMS]; struct draw_vertex_info llvm_vert_info; + struct draw_vertex_info tcs_vert_info; + struct draw_vertex_info tes_vert_info; struct draw_vertex_info gs_vert_info[TGSI_MAX_VERTEX_STREAMS]; struct draw_vertex_info *vert_info; struct draw_prim_info ia_prim_info; @@ -389,6 +580,7 @@ llvm_pipeline_generic(struct draw_pt_middle_end *middle, boolean clipped = 0; unsigned start_or_maxelt, vid_base; const unsigned *elts; + ushort *tes_elts_out = NULL; assert(fetch_info->count > 0); llvm_vert_info.count = fetch_info->count; @@ -436,6 +628,56 @@ llvm_pipeline_generic(struct draw_pt_middle_end *middle, fetch_info = NULL; vert_info = &llvm_vert_info; + if (opt & PT_SHADE) { + struct draw_vertex_shader *vshader = draw->vs.vertex_shader; + if (tcs_shader) { + draw_tess_ctrl_shader_run(tcs_shader, + draw->pt.user.tcs_constants, + draw->pt.user.tcs_constants_size, + vert_info, + prim_info, + &vshader->info, + &tcs_vert_info, + &tcs_prim_info); + FREE(vert_info->verts); + vert_info = &tcs_vert_info; + prim_info = &tcs_prim_info; + + } else if (tes_shader) { + unsigned num_prims = prim_info->count / draw->pt.vertices_per_patch; + tcs_prim_info = *prim_info; + tcs_prim_info.primitive_count = num_prims; + prim_info = &tcs_prim_info; + } + + if (tes_shader) { + draw_tess_eval_shader_run(tes_shader, + draw->pt.user.tes_constants, + draw->pt.user.tes_constants_size, + tcs_shader ? tcs_shader->vertices_out : draw->pt.vertices_per_patch, + vert_info, + prim_info, + tcs_shader ? &tcs_shader->info : &vshader->info, + &tes_vert_info, + &tes_prim_info, &tes_elts_out); + + FREE(vert_info->verts); + vert_info = &tes_vert_info; + prim_info = &tes_prim_info; + free_prim_info = TRUE; + + /* + * pt emit can only handle ushort number of vertices (see + * render->allocate_vertices). + * vsplit guarantees there's never more than 4096, however GS can + * easily blow this up (by a factor of 256 (or even 1024) max). + */ + if (vert_info->count > 65535) { + opt |= PT_PIPELINE; + } + } + } + if ((opt & PT_SHADE) && gshader) { struct draw_vertex_shader *vshader = draw->vs.vertex_shader; draw_geometry_shader_run(gshader, @@ -443,13 +685,18 @@ llvm_pipeline_generic(struct draw_pt_middle_end *middle, draw->pt.user.gs_constants_size, vert_info, prim_info, - &vshader->info, + tes_shader ? &tes_shader->info : &vshader->info, gs_vert_info, gs_prim_info); FREE(vert_info->verts); + if (free_prim_info) { + FREE(prim_info->primitive_lengths); + FREE(tes_elts_out); + } vert_info = &gs_vert_info[0]; prim_info = &gs_prim_info[0]; + free_prim_info = FALSE; /* * pt emit can only handle ushort number of vertices (see * render->allocate_vertices). @@ -477,6 +724,7 @@ llvm_pipeline_generic(struct draw_pt_middle_end *middle, FREE(vert_info->verts); if (free_prim_info) { + FREE(tes_elts_out); FREE(prim_info->primitive_lengths); } return; @@ -492,7 +740,7 @@ llvm_pipeline_generic(struct draw_pt_middle_end *middle, * will try to access non-existent position output. */ if (draw_current_shader_position_output(draw) != -1) { - if ((opt & PT_SHADE) && (gshader || + if ((opt & PT_SHADE) && (gshader || tes_shader || draw->vs.vertex_shader->info.writes_viewport_index)) { clipped = draw_pt_post_vs_run( fpme->post_vs, vert_info, prim_info ); } @@ -512,6 +760,7 @@ llvm_pipeline_generic(struct draw_pt_middle_end *middle, } FREE(vert_info->verts); if (free_prim_info) { + FREE(tes_elts_out); FREE(prim_info->primitive_lengths); } } diff --git a/src/gallium/auxiliary/draw/draw_pt_so_emit.c b/src/gallium/auxiliary/draw/draw_pt_so_emit.c index 6cb38fb9a5e..83f4a31a6ae 100644 --- a/src/gallium/auxiliary/draw/draw_pt_so_emit.c +++ b/src/gallium/auxiliary/draw/draw_pt_so_emit.c @@ -28,6 +28,7 @@ #include "draw/draw_private.h" #include "draw/draw_vs.h" #include "draw/draw_gs.h" +#include "draw/draw_tess.h" #include "draw/draw_context.h" #include "draw/draw_vbuf.h" #include "draw/draw_vertex.h" @@ -60,6 +61,8 @@ draw_so_info(const struct draw_context *draw) if (draw->gs.geometry_shader) { state = &draw->gs.geometry_shader->state.stream_output; + } else if (draw->tes.tess_eval_shader) { + state = &draw->tes.tess_eval_shader->state.stream_output; } else { state = &draw->vs.vertex_shader->state.stream_output; } diff --git a/src/gallium/auxiliary/draw/draw_split_tmp.h b/src/gallium/auxiliary/draw/draw_split_tmp.h index 084699df602..dc6918897e5 100644 --- a/src/gallium/auxiliary/draw/draw_split_tmp.h +++ b/src/gallium/auxiliary/draw/draw_split_tmp.h @@ -40,7 +40,11 @@ FUNC(FUNC_VARS) max_count_loop, max_count_fan); } - draw_pt_split_prim(prim, &first, &incr); + if (prim == PIPE_PRIM_PATCHES) { + first = vsplit->draw->pt.vertices_per_patch; + incr = vsplit->draw->pt.vertices_per_patch; + } else + draw_pt_split_prim(prim, &first, &incr); /* sanitize primitive length */ count = draw_pt_trim_count(count, first, incr); if (count < first) @@ -75,6 +79,7 @@ FUNC(FUNC_VARS) * That is, remaining is implicitly trimmed. */ switch (prim) { + case PIPE_PRIM_PATCHES: case PIPE_PRIM_POINTS: case PIPE_PRIM_LINES: case PIPE_PRIM_LINE_STRIP: