draw: hook up final bits of tessellation

This hooks tessellation into various parts of draw, so the
tessellation shaders are used in the correct places as the
last shader of the pipeline.

Reviewed-by: Roland Scheidegger <sroland@vmware.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/3841>
This commit is contained in:
Dave Airlie 2020-02-17 17:13:11 +10:00
parent 0d02a7b8ca
commit dacf8f5f5c
9 changed files with 446 additions and 41 deletions

View File

@ -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];
}

View File

@ -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

View File

@ -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: \

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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: