#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"
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);
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");
}
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);
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");
}
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;
}
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;
}
}
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;
}
}
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;
}
}
{
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;
}
{
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;
}
{
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;
}
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];
}
{
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;
}
{
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;
}
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;
(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];
+}
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;
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
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: \
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;
}
{
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;
}
{
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];
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];
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;
}
}
#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"
{
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;
}
#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"
*/
{
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;
if (draw_need_pipeline(draw,
draw->rasterizer,
- gs_out_prim)) {
+ out_prim)) {
opt |= PT_PIPELINE;
}
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);
#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"
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
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;
if (gs) {
llvm_middle_end_prepare_gs(fpme);
}
+ if (tcs) {
+ llvm_middle_end_prepare_tcs(fpme);
+ }
+ if (tes) {
+ llvm_middle_end_prepare_tes(fpme);
+ }
}
}
}
+ 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 =
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;
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;
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,
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).
FREE(vert_info->verts);
if (free_prim_info) {
+ FREE(tes_elts_out);
FREE(prim_info->primitive_lengths);
}
return;
* 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 );
}
}
FREE(vert_info->verts);
if (free_prim_info) {
+ FREE(tes_elts_out);
FREE(prim_info->primitive_lengths);
}
}
#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"
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;
}
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)
* 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: