From: Marek Olšák Date: Fri, 9 Dec 2011 17:33:58 +0000 (+0100) Subject: st/mesa: implement EXT_transform_feedback and ARB_transform_feedback2 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=c05fafa4a0fd93d4264c46578e23a83ecf2b481e;p=mesa.git st/mesa: implement EXT_transform_feedback and ARB_transform_feedback2 --- diff --git a/src/gallium/auxiliary/cso_cache/cso_context.c b/src/gallium/auxiliary/cso_cache/cso_context.c index b2a2b79b09a..49318e7d105 100644 --- a/src/gallium/auxiliary/cso_cache/cso_context.c +++ b/src/gallium/auxiliary/cso_cache/cso_context.c @@ -79,6 +79,7 @@ struct cso_context { struct cso_cache *cache; boolean has_geometry_shader; + boolean has_streamout; struct sampler_info fragment_samplers; struct sampler_info vertex_samplers; @@ -89,6 +90,12 @@ struct cso_context { uint nr_vertex_buffers_saved; struct pipe_vertex_buffer vertex_buffers_saved[PIPE_MAX_ATTRIBS]; + unsigned nr_so_targets; + struct pipe_stream_output_target *so_targets[PIPE_MAX_SO_BUFFERS]; + + unsigned nr_so_targets_saved; + struct pipe_stream_output_target *so_targets_saved[PIPE_MAX_SO_BUFFERS]; + /** Current and saved state. * The saved state is used as a 1-deep stack. */ @@ -276,6 +283,10 @@ struct cso_context *cso_create_context( struct pipe_context *pipe ) PIPE_SHADER_CAP_MAX_INSTRUCTIONS) > 0) { ctx->has_geometry_shader = TRUE; } + if (pipe->screen->get_param(pipe->screen, + PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS) != 0) { + ctx->has_streamout = TRUE; + } return ctx; @@ -306,6 +317,7 @@ void cso_release_all( struct cso_context *ctx ) ctx->pipe->set_fragment_sampler_views(ctx->pipe, 0, NULL); if (ctx->pipe->set_vertex_sampler_views) ctx->pipe->set_vertex_sampler_views(ctx->pipe, 0, NULL); + ctx->pipe->set_stream_output_targets(ctx->pipe, 0, NULL, 0); } /* free fragment samplers, views */ @@ -332,6 +344,11 @@ void cso_release_all( struct cso_context *ctx ) &ctx->nr_vertex_buffers_saved, NULL, 0); + for (i = 0; i < PIPE_MAX_SO_BUFFERS; i++) { + pipe_so_target_reference(&ctx->so_targets[i], NULL); + pipe_so_target_reference(&ctx->so_targets_saved[i], NULL); + } + if (ctx->cache) { cso_cache_delete( ctx->cache ); ctx->cache = NULL; @@ -1311,3 +1328,87 @@ cso_restore_vertex_sampler_views(struct cso_context *ctx) restore_sampler_views(ctx, &ctx->vertex_samplers, ctx->pipe->set_vertex_sampler_views); } + + +void +cso_set_stream_outputs(struct cso_context *ctx, + unsigned num_targets, + struct pipe_stream_output_target **targets, + unsigned append_bitmask) +{ + struct pipe_context *pipe = ctx->pipe; + uint i; + + if (!ctx->has_streamout) { + assert(num_targets == 0); + return; + } + + if (ctx->nr_so_targets == 0 && num_targets == 0) { + /* Nothing to do. */ + return; + } + + /* reference new targets */ + for (i = 0; i < num_targets; i++) { + pipe_so_target_reference(&ctx->so_targets[i], targets[i]); + } + /* unref extra old targets, if any */ + for (; i < ctx->nr_so_targets; i++) { + pipe_so_target_reference(&ctx->so_targets[i], NULL); + } + + pipe->set_stream_output_targets(pipe, num_targets, targets, + append_bitmask); + ctx->nr_so_targets = num_targets; +} + +void +cso_save_stream_outputs(struct cso_context *ctx) +{ + uint i; + + if (!ctx->has_streamout) { + return; + } + + ctx->nr_so_targets_saved = ctx->nr_so_targets; + + for (i = 0; i < ctx->nr_so_targets; i++) { + assert(!ctx->so_targets_saved[i]); + pipe_so_target_reference(&ctx->so_targets_saved[i], ctx->so_targets[i]); + } +} + +void +cso_restore_stream_outputs(struct cso_context *ctx) +{ + struct pipe_context *pipe = ctx->pipe; + uint i; + + if (!ctx->has_streamout) { + return; + } + + if (ctx->nr_so_targets == 0 && ctx->nr_so_targets_saved == 0) { + /* Nothing to do. */ + return; + } + + for (i = 0; i < ctx->nr_so_targets_saved; i++) { + pipe_so_target_reference(&ctx->so_targets[i], NULL); + /* move the reference from one pointer to another */ + ctx->so_targets[i] = ctx->so_targets_saved[i]; + ctx->so_targets_saved[i] = NULL; + } + for (; i < ctx->nr_so_targets; i++) { + pipe_so_target_reference(&ctx->so_targets[i], NULL); + } + + /* ~0 means append */ + pipe->set_stream_output_targets(pipe, ctx->nr_so_targets_saved, + ctx->so_targets, ~0); + + ctx->nr_so_targets = ctx->nr_so_targets_saved; + ctx->nr_so_targets_saved = 0; +} diff --git a/src/gallium/auxiliary/cso_cache/cso_context.h b/src/gallium/auxiliary/cso_cache/cso_context.h index 00edc9f8dd4..5102d706e33 100644 --- a/src/gallium/auxiliary/cso_cache/cso_context.h +++ b/src/gallium/auxiliary/cso_cache/cso_context.h @@ -117,6 +117,14 @@ void cso_save_vertex_buffers(struct cso_context *ctx); void cso_restore_vertex_buffers(struct cso_context *ctx); +void cso_set_stream_outputs(struct cso_context *ctx, + unsigned num_targets, + struct pipe_stream_output_target **targets, + unsigned append_bitmask); +void cso_save_stream_outputs(struct cso_context *ctx); +void cso_restore_stream_outputs(struct cso_context *ctx); + + /* These aren't really sensible -- most of the time the api provides * object semantics for shaders anyway, and the cases where it doesn't * (eg mesa's internall-generated texenv programs), it will be up to diff --git a/src/gallium/auxiliary/util/u_blit.c b/src/gallium/auxiliary/util/u_blit.c index 3a0d7d42406..bba0031d772 100644 --- a/src/gallium/auxiliary/util/u_blit.c +++ b/src/gallium/auxiliary/util/u_blit.c @@ -529,6 +529,7 @@ util_blit_pixels_writemask(struct blit_state *ctx, cso_save_rasterizer(ctx->cso); cso_save_samplers(ctx->cso); cso_save_fragment_sampler_views(ctx->cso); + cso_save_stream_outputs(ctx->cso); cso_save_viewport(ctx->cso); cso_save_framebuffer(ctx->cso); cso_save_fragment_shader(ctx->cso); @@ -546,6 +547,7 @@ util_blit_pixels_writemask(struct blit_state *ctx, cso_set_rasterizer(ctx->cso, &ctx->rasterizer); cso_set_clip(ctx->cso, &ctx->clip); cso_set_vertex_elements(ctx->cso, 2, ctx->velem); + cso_set_stream_outputs(ctx->cso, 0, NULL, 0); /* sampler */ ctx->sampler.normalized_coords = normalized; @@ -622,6 +624,7 @@ util_blit_pixels_writemask(struct blit_state *ctx, cso_restore_clip(ctx->cso); cso_restore_vertex_elements(ctx->cso); cso_restore_vertex_buffers(ctx->cso); + cso_restore_stream_outputs(ctx->cso); pipe_sampler_view_reference(&sampler_view, NULL); if (dst_surface != dst) @@ -722,6 +725,7 @@ util_blit_pixels_tex(struct blit_state *ctx, cso_save_rasterizer(ctx->cso); cso_save_samplers(ctx->cso); cso_save_fragment_sampler_views(ctx->cso); + cso_save_stream_outputs(ctx->cso); cso_save_viewport(ctx->cso); cso_save_framebuffer(ctx->cso); cso_save_fragment_shader(ctx->cso); @@ -737,6 +741,7 @@ util_blit_pixels_tex(struct blit_state *ctx, cso_set_rasterizer(ctx->cso, &ctx->rasterizer); cso_set_clip(ctx->cso, &ctx->clip); cso_set_vertex_elements(ctx->cso, 2, ctx->velem); + cso_set_stream_outputs(ctx->cso, 0, NULL, 0); /* sampler */ ctx->sampler.normalized_coords = normalized; @@ -801,4 +806,5 @@ util_blit_pixels_tex(struct blit_state *ctx, cso_restore_clip(ctx->cso); cso_restore_vertex_elements(ctx->cso); cso_restore_vertex_buffers(ctx->cso); + cso_restore_stream_outputs(ctx->cso); } diff --git a/src/gallium/auxiliary/util/u_gen_mipmap.c b/src/gallium/auxiliary/util/u_gen_mipmap.c index 436a0e42456..7cce815beba 100644 --- a/src/gallium/auxiliary/util/u_gen_mipmap.c +++ b/src/gallium/auxiliary/util/u_gen_mipmap.c @@ -1558,6 +1558,7 @@ util_gen_mipmap(struct gen_mipmap_state *ctx, cso_save_rasterizer(ctx->cso); cso_save_samplers(ctx->cso); cso_save_fragment_sampler_views(ctx->cso); + cso_save_stream_outputs(ctx->cso); cso_save_framebuffer(ctx->cso); cso_save_fragment_shader(ctx->cso); cso_save_vertex_shader(ctx->cso); @@ -1572,6 +1573,7 @@ util_gen_mipmap(struct gen_mipmap_state *ctx, cso_set_rasterizer(ctx->cso, &ctx->rasterizer); cso_set_clip(ctx->cso, &ctx->clip); cso_set_vertex_elements(ctx->cso, 2, ctx->velem); + cso_set_stream_outputs(ctx->cso, 0, NULL, 0); set_fragment_shader(ctx, type); set_vertex_shader(ctx); @@ -1688,4 +1690,5 @@ util_gen_mipmap(struct gen_mipmap_state *ctx, cso_restore_viewport(ctx->cso); cso_restore_clip(ctx->cso); cso_restore_vertex_elements(ctx->cso); + cso_restore_stream_outputs(ctx->cso); } diff --git a/src/mesa/state_tracker/st_atom_rasterizer.c b/src/mesa/state_tracker/st_atom_rasterizer.c index 250cbb2260c..4aa0b4e2aa6 100644 --- a/src/mesa/state_tracker/st_atom_rasterizer.c +++ b/src/mesa/state_tracker/st_atom_rasterizer.c @@ -256,9 +256,11 @@ static void update_raster_state( struct st_context *st ) /* _NEW_FRAG_CLAMP */ raster->clamp_fragment_color = ctx->Color._ClampFragmentColor; - raster->gl_rasterization_rules = 1; + /* _NEW_TRANSFORM */ + raster->rasterizer_discard = ctx->TransformFeedback.RasterDiscard; + cso_set_rasterizer(st->cso_context, raster); } @@ -273,7 +275,8 @@ const struct st_tracked_state st_update_rasterizer = { _NEW_POLYGON | _NEW_PROGRAM | _NEW_SCISSOR | - _NEW_FRAG_CLAMP), /* mesa state dependencies*/ + _NEW_FRAG_CLAMP | + _NEW_TRANSFORM), /* mesa state dependencies*/ ST_NEW_VERTEX_PROGRAM, /* state tracker dependencies */ }, update_raster_state /* update function */ diff --git a/src/mesa/state_tracker/st_cb_bitmap.c b/src/mesa/state_tracker/st_cb_bitmap.c index fa37be0b66f..af33bcf8605 100644 --- a/src/mesa/state_tracker/st_cb_bitmap.c +++ b/src/mesa/state_tracker/st_cb_bitmap.c @@ -483,6 +483,7 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, cso_save_fragment_sampler_views(cso); cso_save_viewport(cso); cso_save_fragment_shader(cso); + cso_save_stream_outputs(cso); cso_save_vertex_shader(cso); cso_save_geometry_shader(cso); cso_save_vertex_elements(cso); @@ -542,6 +543,7 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, } cso_set_vertex_elements(cso, 3, st->velems_util_draw); + cso_set_stream_outputs(st->cso_context, 0, NULL, 0); /* convert Z from [0,1] to [-1,-1] to match viewport Z scale/bias */ z = z * 2.0f - 1.0f; @@ -568,6 +570,7 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, cso_restore_geometry_shader(cso); cso_restore_vertex_elements(cso); cso_restore_vertex_buffers(cso); + cso_restore_stream_outputs(cso); } diff --git a/src/mesa/state_tracker/st_cb_clear.c b/src/mesa/state_tracker/st_cb_clear.c index 61d98aeb9a3..23700eeb7ed 100644 --- a/src/mesa/state_tracker/st_cb_clear.c +++ b/src/mesa/state_tracker/st_cb_clear.c @@ -250,6 +250,7 @@ clear_with_quad(struct gl_context *ctx, cso_save_viewport(st->cso_context); cso_save_clip(st->cso_context); cso_save_fragment_shader(st->cso_context); + cso_save_stream_outputs(st->cso_context); cso_save_vertex_shader(st->cso_context); cso_save_geometry_shader(st->cso_context); cso_save_vertex_elements(st->cso_context); @@ -306,6 +307,7 @@ clear_with_quad(struct gl_context *ctx, } cso_set_vertex_elements(st->cso_context, 2, st->velems_util_draw); + cso_set_stream_outputs(st->cso_context, 0, NULL, 0); cso_set_rasterizer(st->cso_context, &st->clear.raster); @@ -350,6 +352,7 @@ clear_with_quad(struct gl_context *ctx, cso_restore_geometry_shader(st->cso_context); cso_restore_vertex_elements(st->cso_context); cso_restore_vertex_buffers(st->cso_context); + cso_restore_stream_outputs(st->cso_context); } diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c index 65b4445521c..318ba7d0628 100644 --- a/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/src/mesa/state_tracker/st_cb_drawpixels.c @@ -671,6 +671,7 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, cso_save_samplers(cso); cso_save_fragment_sampler_views(cso); cso_save_fragment_shader(cso); + cso_save_stream_outputs(cso); cso_save_vertex_shader(cso); cso_save_geometry_shader(cso); cso_save_vertex_elements(cso); @@ -761,6 +762,7 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, } cso_set_vertex_elements(cso, 3, st->velems_util_draw); + cso_set_stream_outputs(st->cso_context, 0, NULL, 0); /* texture state: */ cso_set_fragment_sampler_views(cso, num_sampler_view, sv); @@ -796,6 +798,7 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, cso_restore_geometry_shader(cso); cso_restore_vertex_elements(cso); cso_restore_vertex_buffers(cso); + cso_restore_stream_outputs(cso); if (write_stencil) { cso_restore_depth_stencil_alpha(cso); cso_restore_blend(cso); diff --git a/src/mesa/state_tracker/st_cb_drawtex.c b/src/mesa/state_tracker/st_cb_drawtex.c index 332b0d1b62d..6144eb99c87 100644 --- a/src/mesa/state_tracker/st_cb_drawtex.c +++ b/src/mesa/state_tracker/st_cb_drawtex.c @@ -227,6 +227,7 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z, cso_save_viewport(cso); + cso_save_stream_outputs(cso); cso_save_vertex_shader(cso); cso_save_geometry_shader(cso); cso_save_vertex_elements(cso); @@ -246,6 +247,7 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z, velements[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; } cso_set_vertex_elements(cso, numAttribs, velements); + cso_set_stream_outputs(st->cso_context, 0, NULL, 0); /* viewport state: viewport matching window dims */ { @@ -281,6 +283,7 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z, cso_restore_geometry_shader(cso); cso_restore_vertex_elements(cso); cso_restore_vertex_buffers(cso); + cso_restore_stream_outputs(cso); } diff --git a/src/mesa/state_tracker/st_cb_xformfb.c b/src/mesa/state_tracker/st_cb_xformfb.c index a17b54d326e..2fc28dc2444 100644 --- a/src/mesa/state_tracker/st_cb_xformfb.c +++ b/src/mesa/state_tracker/st_cb_xformfb.c @@ -30,70 +30,122 @@ * Transform feedback functions. * * \author Brian Paul + * Marek Olšák */ -#include "main/imports.h" +#include "main/bufferobj.h" #include "main/context.h" #include "main/mfeatures.h" #include "main/transformfeedback.h" +#include "st_cb_bufferobjects.h" #include "st_cb_xformfb.h" +#include "st_context.h" +#include "pipe/p_context.h" +#include "util/u_draw.h" +#include "util/u_inlines.h" +#include "cso_cache/cso_context.h" #if FEATURE_EXT_transform_feedback -#if 0 +struct st_transform_feedback_object { + struct gl_transform_feedback_object base; + + unsigned num_targets; + struct pipe_stream_output_target *targets[PIPE_MAX_SO_BUFFERS]; +}; + + static struct gl_transform_feedback_object * st_new_transform_feedback(struct gl_context *ctx, GLuint name) { - struct gl_transform_feedback_object *obj; - obj = CALLOC_STRUCT(gl_transform_feedback_object); - if (obj) { - obj->Name = name; - obj->RefCount = 1; - } - return obj; + struct st_transform_feedback_object *obj; + + obj = CALLOC_STRUCT(st_transform_feedback_object); + if (!obj) + return NULL; + + obj->base.Name = name; + obj->base.RefCount = 1; + return &obj->base; } -#endif -#if 0 + static void st_delete_transform_feedback(struct gl_context *ctx, struct gl_transform_feedback_object *obj) { - GLuint i; + struct st_transform_feedback_object *sobj = + (struct st_transform_feedback_object*)obj; + unsigned i; + + /* Unreference targets. */ + for (i = 0; i < sobj->num_targets; i++) { + pipe_so_target_reference(&sobj->targets[i], NULL); + } - for (i = 0; i < Elements(obj->Buffers); i++) { - _mesa_reference_buffer_object(ctx, &obj->Buffers[i], NULL); + for (i = 0; i < Elements(sobj->base.Buffers); i++) { + _mesa_reference_buffer_object(ctx, &sobj->base.Buffers[i], NULL); } free(obj); } -#endif +/* XXX Do we really need the mode? */ static void st_begin_transform_feedback(struct gl_context *ctx, GLenum mode, struct gl_transform_feedback_object *obj) { - /* to-do */ -} - + struct st_context *st = st_context(ctx); + struct pipe_context *pipe = st->pipe; + struct st_transform_feedback_object *sobj = + (struct st_transform_feedback_object*)obj; + unsigned i, max_num_targets; + + max_num_targets = MIN2(Elements(sobj->base.Buffers), + Elements(sobj->targets)); + + /* Convert the transform feedback state into the gallium representation. */ + for (i = 0; i < max_num_targets; i++) { + struct st_buffer_object *bo = st_buffer_object(sobj->base.Buffers[i]); + + if (bo) { + /* Check whether we need to recreate the target. */ + if (!sobj->targets[i] || + sobj->targets[i]->buffer != bo->buffer || + sobj->targets[i]->buffer_offset != sobj->base.Offset[i] || + sobj->targets[i]->buffer_size != sobj->base.Size[i]) { + /* Create a new target. */ + struct pipe_stream_output_target *so_target = + pipe->create_stream_output_target(pipe, bo->buffer, + sobj->base.Offset[i], + sobj->base.Size[i]); + + pipe_so_target_reference(&sobj->targets[i], NULL); + sobj->targets[i] = so_target; + } + + sobj->num_targets = i+1; + } else { + pipe_so_target_reference(&sobj->targets[i], NULL); + } + } -static void -st_end_transform_feedback(struct gl_context *ctx, - struct gl_transform_feedback_object *obj) -{ - /* to-do */ + /* Start writing at the beginning of each target. */ + cso_set_stream_outputs(st->cso_context, sobj->num_targets, sobj->targets, + 0); } static void -st_pause_transform_feedback(struct gl_context *ctx, - struct gl_transform_feedback_object *obj) +st_stop_transform_feedback(struct gl_context *ctx, + struct gl_transform_feedback_object *obj) { - /* to-do */ + struct st_context *st = st_context(ctx); + cso_set_stream_outputs(st->cso_context, 0, NULL, 0); } @@ -101,20 +153,44 @@ static void st_resume_transform_feedback(struct gl_context *ctx, struct gl_transform_feedback_object *obj) { - /* to-do */ + struct st_context *st = st_context(ctx); + struct st_transform_feedback_object *sobj = + (struct st_transform_feedback_object*)obj; + + cso_set_stream_outputs(st->cso_context, sobj->num_targets, sobj->targets, + ~0); +} + +/* Set count_from_stream_output to any stream output target + * from the transform feedback object. */ +void +st_transform_feedback_draw_init(struct gl_transform_feedback_object *obj, + struct pipe_draw_info *out) +{ + struct st_transform_feedback_object *sobj = + (struct st_transform_feedback_object*)obj; + unsigned i; + + for (i = 0; i < Elements(sobj->targets); i++) { + if (sobj->targets[i]) { + out->count_from_stream_output = sobj->targets[i]; + return; + } + } + + assert(0); + out->count_from_stream_output = NULL; } void st_init_xformfb_functions(struct dd_function_table *functions) { - /* let core Mesa plug in its functions */ - _mesa_init_transform_feedback_functions(functions); - - /* then override a few: */ + functions->NewTransformFeedback = st_new_transform_feedback; + functions->DeleteTransformFeedback = st_delete_transform_feedback; functions->BeginTransformFeedback = st_begin_transform_feedback; - functions->EndTransformFeedback = st_end_transform_feedback; - functions->PauseTransformFeedback = st_pause_transform_feedback; + functions->EndTransformFeedback = st_stop_transform_feedback; + functions->PauseTransformFeedback = st_stop_transform_feedback; functions->ResumeTransformFeedback = st_resume_transform_feedback; } diff --git a/src/mesa/state_tracker/st_cb_xformfb.h b/src/mesa/state_tracker/st_cb_xformfb.h index 1215ebea871..c5261b39b94 100644 --- a/src/mesa/state_tracker/st_cb_xformfb.h +++ b/src/mesa/state_tracker/st_cb_xformfb.h @@ -33,12 +33,18 @@ #include "main/mfeatures.h" struct dd_function_table; +struct gl_transform_feedback_object; +struct pipe_draw_info; #if FEATURE_EXT_transform_feedback extern void st_init_xformfb_functions(struct dd_function_table *functions); +extern void +st_transform_feedback_draw_init(struct gl_transform_feedback_object *obj, + struct pipe_draw_info *out); + #else static INLINE void @@ -46,6 +52,12 @@ st_init_xformfb_functions(struct dd_function_table *functions) { } +static INLINE void +st_transform_feedback_draw_init(struct gl_transform_feedback_object *obj, + struct pipe_draw_info *out) +{ +} + #endif /* FEATURE_EXT_transform_feedback */ #endif /* ST_CB_XFORMFB_H */ diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c index 86478bbceba..87a99786521 100644 --- a/src/mesa/state_tracker/st_draw.c +++ b/src/mesa/state_tracker/st_draw.c @@ -51,6 +51,7 @@ #include "st_context.h" #include "st_atom.h" #include "st_cb_bufferobjects.h" +#include "st_cb_xformfb.h" #include "st_draw.h" #include "st_program.h" @@ -940,7 +941,6 @@ st_draw_vbo(struct gl_context *ctx, /* Mesa core state should have been validated already */ assert(ctx->NewState == 0x0); - assert(!tfb_vertcount); if (ib) { /* Gallium probably doesn't want this in some cases. */ @@ -1034,6 +1034,11 @@ st_draw_vbo(struct gl_context *ctx, info.restart_index = ctx->Array.RestartIndex; } + /* Set info.count_from_stream_output. */ + if (tfb_vertcount) { + st_transform_feedback_draw_init(tfb_vertcount, &info); + } + /* do actual drawing */ for (i = 0; i < nr_prims; i++) { info.mode = translate_prim( ctx, prims[i].mode ); @@ -1046,7 +1051,10 @@ st_draw_vbo(struct gl_context *ctx, info.max_index = info.start + info.count - 1; } - if (info.primitive_restart) { + if (info.count_from_stream_output) { + pipe->draw_vbo(pipe, &info); + } + else if (info.primitive_restart) { if (st->sw_primitive_restart) { /* Handle primitive restart for drivers that doesn't support it */ handle_fallback_primitive_restart(pipe, ib, &ibuffer, &info); diff --git a/src/mesa/state_tracker/st_extensions.c b/src/mesa/state_tracker/st_extensions.c index 457d5d62a8e..47a178b8b1f 100644 --- a/src/mesa/state_tracker/st_extensions.c +++ b/src/mesa/state_tracker/st_extensions.c @@ -221,6 +221,13 @@ void st_init_limits(struct st_context *st) c->UniformBooleanTrue = ~0; + c->MaxTransformFeedbackSeparateAttribs = + screen->get_param(screen, PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_ATTRIBS); + c->MaxTransformFeedbackSeparateComponents = + screen->get_param(screen, PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS); + c->MaxTransformFeedbackInterleavedComponents = + screen->get_param(screen, PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS); + c->StripTextureBorder = GL_TRUE; c->GLSLSkipStrictMaxUniformLimitCheck = @@ -682,4 +689,12 @@ void st_init_extensions(struct st_context *st) PIPE_BIND_SAMPLER_VIEW)) ctx->Extensions.ARB_texture_rgb10_a2ui = GL_TRUE; + if (screen->get_param(screen, PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS) != 0) { + ctx->Extensions.EXT_transform_feedback = GL_TRUE; + + if (screen->get_param(screen, + PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME) != 0) { + ctx->Extensions.ARB_transform_feedback2 = GL_TRUE; + } + } } diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp index 9ef65c8fdb1..b929806ad3d 100644 --- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -5095,4 +5095,31 @@ st_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) return GL_TRUE; } +void +st_translate_stream_output_info(struct glsl_to_tgsi_visitor *glsl_to_tgsi, + const GLuint outputMapping[], + struct pipe_stream_output_info *so) +{ + static unsigned comps_to_mask[] = { + 0, + TGSI_WRITEMASK_X, + TGSI_WRITEMASK_XY, + TGSI_WRITEMASK_XYZ, + TGSI_WRITEMASK_XYZW + }; + unsigned i; + struct gl_transform_feedback_info *info = + &glsl_to_tgsi->shader_program->LinkedTransformFeedback; + + for (i = 0; i < info->NumOutputs; i++) { + assert(info->Outputs[i].NumComponents < Elements(comps_to_mask)); + so->output[i].register_index = + outputMapping[info->Outputs[i].OutputRegister]; + so->output[i].register_mask = + comps_to_mask[info->Outputs[i].NumComponents]; + so->output[i].output_buffer = info->Outputs[i].OutputBuffer; + } + so->num_outputs = info->NumOutputs; +} + } /* extern "C" */ diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.h b/src/mesa/state_tracker/st_glsl_to_tgsi.h index fafe52e31ee..1f71f33fd47 100644 --- a/src/mesa/state_tracker/st_glsl_to_tgsi.h +++ b/src/mesa/state_tracker/st_glsl_to_tgsi.h @@ -66,6 +66,12 @@ st_new_shader_program(struct gl_context *ctx, GLuint name); GLboolean st_link_shader(struct gl_context *ctx, struct gl_shader_program *prog); +void +st_translate_stream_output_info(struct glsl_to_tgsi_visitor *glsl_to_tgsi, + const GLuint outputMapping[], + struct pipe_stream_output_info *so); + + #ifdef __cplusplus } #endif diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c index 04d3ef60f51..b83c561651d 100644 --- a/src/mesa/state_tracker/st_program.c +++ b/src/mesa/state_tracker/st_program.c @@ -367,6 +367,12 @@ st_translate_vertex_program(struct st_context *st, ureg_destroy( ureg ); + if (stvp->glsl_to_tgsi) { + st_translate_stream_output_info(stvp->glsl_to_tgsi, + stvp->result_to_output, + &vpv->tgsi.stream_output); + } + vpv->driver_shader = pipe->create_vs_state(pipe, &vpv->tgsi); if (ST_DEBUG & DEBUG_TGSI) { @@ -994,6 +1000,12 @@ st_translate_geometry_program(struct st_context *st, stgp->tgsi.tokens = ureg_get_tokens( ureg, NULL ); ureg_destroy( ureg ); + if (stgp->glsl_to_tgsi) { + st_translate_stream_output_info(stgp->glsl_to_tgsi, + outputMapping, + &stgp->tgsi.stream_output); + } + /* fill in new variant */ gpv->driver_shader = pipe->create_gs_state(pipe, &stgp->tgsi); gpv->key = *key;