summaryrefslogtreecommitdiffstats
path: root/src/mesa
diff options
context:
space:
mode:
authorMarek Olšák <[email protected]>2011-12-09 18:33:58 +0100
committerChristoph Bumiller <[email protected]>2011-12-15 18:51:48 +0100
commitc05fafa4a0fd93d4264c46578e23a83ecf2b481e (patch)
treed53751c909b147934d727bc9a276d331a38ed61c /src/mesa
parent36d66f8d4ad1e2b18bb28d0b08e98f968ad6137e (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.c7
-rw-r--r--src/mesa/state_tracker/st_cb_bitmap.c3
-rw-r--r--src/mesa/state_tracker/st_cb_clear.c3
-rw-r--r--src/mesa/state_tracker/st_cb_drawpixels.c3
-rw-r--r--src/mesa/state_tracker/st_cb_drawtex.c3
-rw-r--r--src/mesa/state_tracker/st_cb_xformfb.c142
-rw-r--r--src/mesa/state_tracker/st_cb_xformfb.h12
-rw-r--r--src/mesa/state_tracker/st_draw.c12
-rw-r--r--src/mesa/state_tracker/st_extensions.c15
-rw-r--r--src/mesa/state_tracker/st_glsl_to_tgsi.cpp27
-rw-r--r--src/mesa/state_tracker/st_glsl_to_tgsi.h6
-rw-r--r--src/mesa/state_tracker/st_program.c12
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;