#include "draw/draw_vertex.h"
#include "draw/draw_pt.h"
#include "draw/draw_vs.h"
-#include "translate/translate.h"
+#include "draw/draw_gs.h"
struct fetch_pipeline_middle_end {
struct draw_context *draw;
struct pt_emit *emit;
+ struct pt_so_emit *so_emit;
struct pt_fetch *fetch;
struct pt_post_vs *post_vs;
unsigned vertex_data_offset;
unsigned vertex_size;
- unsigned prim;
+ unsigned input_prim;
+ unsigned output_prim;
unsigned opt;
};
static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
- unsigned prim,
+ unsigned in_prim,
+ unsigned out_prim,
unsigned opt,
unsigned *max_vertices )
{
struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
struct draw_context *draw = fpme->draw;
struct draw_vertex_shader *vs = draw->vs.vertex_shader;
+ unsigned i;
+ unsigned instance_id_index = ~0;
/* Add one to num_outputs because the pipeline occasionally tags on
* an additional texcoord, eg for AA lines.
unsigned nr = MAX2( vs->info.num_inputs,
vs->info.num_outputs + 1 );
- fpme->prim = prim;
+ /* Scan for instanceID system value.
+ */
+ for (i = 0; i < vs->info.num_inputs; i++) {
+ if (vs->info.input_semantic_name[i] == TGSI_SEMANTIC_INSTANCEID) {
+ instance_id_index = i;
+ break;
+ }
+ }
+
+ fpme->input_prim = in_prim;
+ fpme->output_prim = out_prim;
fpme->opt = opt;
/* Always leave room for the vertex header whether we need it or
draw_pt_fetch_prepare( fpme->fetch,
- fpme->vertex_size );
-
+ vs->info.num_inputs,
+ fpme->vertex_size,
+ instance_id_index );
/* XXX: it's not really gl rasterization rules we care about here,
* but gl vs dx9 clip spaces.
*/
draw_pt_post_vs_prepare( fpme->post_vs,
(boolean)draw->bypass_clipping,
(boolean)draw->identity_viewport,
- (boolean)draw->rasterizer->gl_rasterization_rules );
-
+ (boolean)draw->rasterizer->gl_rasterization_rules,
+ (draw->vs.edgeflag_output ? true : false) );
+
+ draw_pt_so_emit_prepare( fpme->so_emit, out_prim );
if (!(opt & PT_PIPELINE)) {
- draw_pt_emit_prepare( fpme->emit,
- prim,
+ draw_pt_emit_prepare( fpme->emit,
+ out_prim,
max_vertices );
*max_vertices = MAX2( *max_vertices,
{
struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
struct draw_context *draw = fpme->draw;
- struct draw_vertex_shader *shader = draw->vs.vertex_shader;
+ struct draw_vertex_shader *vshader = draw->vs.vertex_shader;
+ struct draw_geometry_shader *gshader = draw->gs.geometry_shader;
unsigned opt = fpme->opt;
+ struct vertex_header *pipeline_verts;
unsigned alloc_count = align( fetch_count, 4 );
- struct vertex_header *pipeline_verts =
+ if (draw->gs.geometry_shader &&
+ draw->gs.geometry_shader->max_output_vertices > fetch_count) {
+ alloc_count = align(draw->gs.geometry_shader->max_output_vertices, 4);
+ }
+
+ pipeline_verts =
(struct vertex_header *)MALLOC(fpme->vertex_size * alloc_count);
if (!pipeline_verts) {
(char *)pipeline_verts );
/* Run the shader, note that this overwrites the data[] parts of
- * the pipeline verts. If there is no shader, ie a bypass shader,
- * then the inputs == outputs, and are already in the correct
- * place.
+ * the pipeline verts.
*/
if (opt & PT_SHADE)
{
- shader->run_linear(shader,
- (const float (*)[4])pipeline_verts->data,
- ( float (*)[4])pipeline_verts->data,
- (const float (*)[4])draw->pt.user.constants,
- fetch_count,
- fpme->vertex_size,
- fpme->vertex_size);
+ vshader->run_linear(vshader,
+ (const float (*)[4])pipeline_verts->data,
+ ( float (*)[4])pipeline_verts->data,
+ draw->pt.user.vs_constants,
+ fetch_count,
+ fpme->vertex_size,
+ fpme->vertex_size);
+ if (gshader)
+ fetch_count =
+ draw_geometry_shader_run(gshader,
+ (const float (*)[4])pipeline_verts->data,
+ ( float (*)[4])pipeline_verts->data,
+ draw->pt.user.gs_constants,
+ fetch_count,
+ fpme->vertex_size,
+ fpme->vertex_size);
}
+ /* stream output needs to be done before clipping */
+ draw_pt_so_emit( fpme->so_emit,
+ (const float (*)[4])pipeline_verts->data,
+ fetch_count,
+ fpme->vertex_size );
+
if (draw_pt_post_vs_run( fpme->post_vs,
pipeline_verts,
fetch_count,
*/
if (opt & PT_PIPELINE) {
draw_pipeline_run( fpme->draw,
- fpme->prim,
+ fpme->output_prim,
pipeline_verts,
fetch_count,
fpme->vertex_size,
struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
struct draw_context *draw = fpme->draw;
struct draw_vertex_shader *shader = draw->vs.vertex_shader;
+ struct draw_geometry_shader *geometry_shader = draw->gs.geometry_shader;
unsigned opt = fpme->opt;
+ struct vertex_header *pipeline_verts;
unsigned alloc_count = align( count, 4 );
- struct vertex_header *pipeline_verts =
+ if (geometry_shader && geometry_shader->max_output_vertices > count) {
+ alloc_count = align(geometry_shader->max_output_vertices, 4);
+ }
+
+ pipeline_verts =
(struct vertex_header *)MALLOC(fpme->vertex_size * alloc_count);
if (!pipeline_verts) {
(char *)pipeline_verts );
/* Run the shader, note that this overwrites the data[] parts of
- * the pipeline verts. If there is no shader, ie a bypass shader,
- * then the inputs == outputs, and are already in the correct
- * place.
+ * the pipeline verts.
*/
if (opt & PT_SHADE)
{
shader->run_linear(shader,
(const float (*)[4])pipeline_verts->data,
( float (*)[4])pipeline_verts->data,
- (const float (*)[4])draw->pt.user.constants,
+ draw->pt.user.vs_constants,
count,
fpme->vertex_size,
fpme->vertex_size);
+
+ if (geometry_shader)
+ count = draw_geometry_shader_run(geometry_shader,
+ (const float (*)[4])pipeline_verts->data,
+ ( float (*)[4])pipeline_verts->data,
+ draw->pt.user.gs_constants,
+ count,
+ fpme->vertex_size,
+ fpme->vertex_size);
}
+ /* stream output needs to be done before clipping */
+ draw_pt_so_emit( fpme->so_emit,
+ (const float (*)[4])pipeline_verts->data,
+ count,
+ fpme->vertex_size );
+
if (draw_pt_post_vs_run( fpme->post_vs,
pipeline_verts,
count,
*/
if (opt & PT_PIPELINE) {
draw_pipeline_run_linear( fpme->draw,
- fpme->prim,
+ fpme->output_prim,
pipeline_verts,
count,
fpme->vertex_size);
else {
draw_pt_emit_linear( fpme->emit,
(const float (*)[4])pipeline_verts->data,
- count,
fpme->vertex_size,
- 0, /*start*/
count );
}
struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
struct draw_context *draw = fpme->draw;
struct draw_vertex_shader *shader = draw->vs.vertex_shader;
+ struct draw_geometry_shader *geometry_shader = draw->gs.geometry_shader;
unsigned opt = fpme->opt;
+ struct vertex_header *pipeline_verts;
unsigned alloc_count = align( count, 4 );
- struct vertex_header *pipeline_verts =
+ if (draw->gs.geometry_shader &&
+ draw->gs.geometry_shader->max_output_vertices > count) {
+ alloc_count = align(draw->gs.geometry_shader->max_output_vertices, 4);
+ }
+
+ pipeline_verts =
(struct vertex_header *)MALLOC(fpme->vertex_size * alloc_count);
- if (!pipeline_verts)
+ if (!pipeline_verts)
return FALSE;
/* Fetch into our vertex buffer
(char *)pipeline_verts );
/* Run the shader, note that this overwrites the data[] parts of
- * the pipeline verts. If there is no shader, ie a bypass shader,
- * then the inputs == outputs, and are already in the correct
- * place.
+ * the pipeline verts.
*/
if (opt & PT_SHADE)
{
shader->run_linear(shader,
(const float (*)[4])pipeline_verts->data,
( float (*)[4])pipeline_verts->data,
- (const float (*)[4])draw->pt.user.constants,
+ draw->pt.user.vs_constants,
count,
fpme->vertex_size,
fpme->vertex_size);
+
+ if (geometry_shader)
+ count = draw_geometry_shader_run(geometry_shader,
+ (const float (*)[4])pipeline_verts->data,
+ ( float (*)[4])pipeline_verts->data,
+ draw->pt.user.gs_constants,
+ count,
+ fpme->vertex_size,
+ fpme->vertex_size);
}
+ /* stream output needs to be done before clipping */
+ draw_pt_so_emit( fpme->so_emit,
+ (const float (*)[4])pipeline_verts->data,
+ count,
+ fpme->vertex_size );
+
if (draw_pt_post_vs_run( fpme->post_vs,
pipeline_verts,
count,
*/
if (opt & PT_PIPELINE) {
draw_pipeline_run( fpme->draw,
- fpme->prim,
+ fpme->output_prim,
pipeline_verts,
count,
fpme->vertex_size,
if (fpme->emit)
draw_pt_emit_destroy( fpme->emit );
+ if (fpme->so_emit)
+ draw_pt_so_emit_destroy( fpme->so_emit );
+
if (fpme->post_vs)
draw_pt_post_vs_destroy( fpme->post_vs );
if (!fpme->emit)
goto fail;
+ fpme->so_emit = draw_pt_so_emit_create( draw );
+ if (!fpme->so_emit)
+ goto fail;
+
return &fpme->base;
fail: