diff options
author | Marek Olšák <[email protected]> | 2011-12-09 18:33:58 +0100 |
---|---|---|
committer | Christoph Bumiller <[email protected]> | 2011-12-15 18:51:48 +0100 |
commit | c05fafa4a0fd93d4264c46578e23a83ecf2b481e (patch) | |
tree | d53751c909b147934d727bc9a276d331a38ed61c /src/mesa | |
parent | 36d66f8d4ad1e2b18bb28d0b08e98f968ad6137e (diff) |
st/mesa: implement EXT_transform_feedback and ARB_transform_feedback2
Diffstat (limited to 'src/mesa')
-rw-r--r-- | src/mesa/state_tracker/st_atom_rasterizer.c | 7 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_cb_bitmap.c | 3 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_cb_clear.c | 3 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_cb_drawpixels.c | 3 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_cb_drawtex.c | 3 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_cb_xformfb.c | 142 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_cb_xformfb.h | 12 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_draw.c | 12 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_extensions.c | 15 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 27 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_glsl_to_tgsi.h | 6 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_program.c | 12 |
12 files changed, 208 insertions, 37 deletions
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; |