mesa: add Driver.DrawTransformFeedback
to remove some overhead from Driver.Draw. Reviewed-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7441>
This commit is contained in:
@@ -122,6 +122,7 @@ _mesa_init_driver_functions(struct dd_function_table *driver)
|
||||
/* Draw functions */
|
||||
driver->Draw = NULL;
|
||||
driver->DrawIndirect = NULL;
|
||||
driver->DrawTransformFeedback = NULL;
|
||||
|
||||
/* simple state commands */
|
||||
driver->AlphaFunc = NULL;
|
||||
|
@@ -1140,15 +1140,11 @@ brw_draw_prims(struct gl_context *ctx,
|
||||
GLuint min_index,
|
||||
GLuint max_index,
|
||||
GLuint num_instances,
|
||||
GLuint base_instance,
|
||||
struct gl_transform_feedback_object *gl_xfb_obj,
|
||||
unsigned stream)
|
||||
GLuint base_instance)
|
||||
{
|
||||
unsigned i;
|
||||
struct brw_context *brw = brw_context(ctx);
|
||||
int predicate_state = brw->predicate.state;
|
||||
struct brw_transform_feedback_object *xfb_obj =
|
||||
(struct brw_transform_feedback_object *) gl_xfb_obj;
|
||||
|
||||
if (!brw_check_conditional_render(brw))
|
||||
return;
|
||||
@@ -1169,7 +1165,7 @@ brw_draw_prims(struct gl_context *ctx,
|
||||
_swsetup_Wakeup(ctx);
|
||||
_tnl_wakeup(ctx);
|
||||
_tnl_draw(ctx, prims, nr_prims, ib, index_bounds_valid, min_index,
|
||||
max_index, num_instances, base_instance, NULL, 0);
|
||||
max_index, num_instances, base_instance);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1222,7 +1218,7 @@ brw_draw_prims(struct gl_context *ctx,
|
||||
}
|
||||
|
||||
brw_draw_single_prim(ctx, &prims[i], i, ib != NULL, num_instances,
|
||||
base_instance, xfb_obj, stream,
|
||||
base_instance, NULL, 0,
|
||||
brw->draw.draw_indirect_offset +
|
||||
brw->draw.draw_indirect_stride * i);
|
||||
}
|
||||
@@ -1231,6 +1227,45 @@ brw_draw_prims(struct gl_context *ctx,
|
||||
brw->predicate.state = predicate_state;
|
||||
}
|
||||
|
||||
static void
|
||||
brw_draw_transform_feedback(struct gl_context *ctx, GLenum mode,
|
||||
unsigned num_instances, unsigned stream,
|
||||
struct gl_transform_feedback_object *gl_xfb_obj)
|
||||
{
|
||||
struct brw_context *brw = brw_context(ctx);
|
||||
struct brw_transform_feedback_object *xfb_obj =
|
||||
(struct brw_transform_feedback_object *) gl_xfb_obj;
|
||||
|
||||
if (!brw_check_conditional_render(brw))
|
||||
return;
|
||||
|
||||
/* Do GL_SELECT and GL_FEEDBACK rendering using swrast, even though it
|
||||
* won't support all the extensions we support.
|
||||
*/
|
||||
if (ctx->RenderMode != GL_RENDER) {
|
||||
perf_debug("%s render mode not supported in hardware\n",
|
||||
_mesa_enum_to_string(ctx->RenderMode));
|
||||
/* swrast doesn't support DrawTransformFeedback. Nothing to do. */
|
||||
return;
|
||||
}
|
||||
|
||||
brw_prepare_drawing(ctx, NULL, false, 0, ~0);
|
||||
|
||||
struct _mesa_prim prim;
|
||||
memset(&prim, 0, sizeof(prim));
|
||||
prim.begin = 1;
|
||||
prim.end = 1;
|
||||
prim.mode = mode;
|
||||
|
||||
/* Try drawing with the hardware, but don't do anything else if we can't
|
||||
* manage it. swrast doesn't support our featureset, so we can't fall back
|
||||
* to it.
|
||||
*/
|
||||
brw_draw_single_prim(ctx, &prim, 0, false, num_instances, 0, xfb_obj,
|
||||
stream, 0);
|
||||
brw_finish_drawing(ctx);
|
||||
}
|
||||
|
||||
void
|
||||
brw_draw_indirect_prims(struct gl_context *ctx,
|
||||
GLuint mode,
|
||||
@@ -1274,7 +1309,7 @@ brw_draw_indirect_prims(struct gl_context *ctx,
|
||||
|
||||
brw->draw.draw_indirect_data = indirect_data;
|
||||
|
||||
brw_draw_prims(ctx, prim, draw_count, ib, false, 0, ~0, 0, 0, NULL, 0);
|
||||
brw_draw_prims(ctx, prim, draw_count, ib, false, 0, ~0, 0, 0);
|
||||
|
||||
brw->draw.draw_indirect_data = NULL;
|
||||
free(prim);
|
||||
@@ -1286,6 +1321,7 @@ brw_init_draw_functions(struct dd_function_table *functions)
|
||||
/* Register our drawing function:
|
||||
*/
|
||||
functions->Draw = brw_draw_prims;
|
||||
functions->DrawTransformFeedback = brw_draw_transform_feedback;
|
||||
functions->DrawIndirect = brw_draw_indirect_prims;
|
||||
}
|
||||
|
||||
|
@@ -52,9 +52,7 @@ void brw_draw_prims(struct gl_context *ctx,
|
||||
GLuint min_index,
|
||||
GLuint max_index,
|
||||
GLuint num_instances,
|
||||
GLuint base_instance,
|
||||
struct gl_transform_feedback_object *unused_tfb_object,
|
||||
unsigned stream);
|
||||
GLuint base_instance);
|
||||
|
||||
void brw_init_draw_functions(struct dd_function_table *functions);
|
||||
void brw_draw_init( struct brw_context *brw );
|
||||
|
@@ -163,7 +163,7 @@ brw_handle_primitive_restart(struct gl_context *ctx,
|
||||
*/
|
||||
brw->prim_restart.enable_cut_index = true;
|
||||
brw_draw_prims(ctx, prims, nr_prims, ib, GL_FALSE, -1, -1,
|
||||
num_instances, base_instance, NULL, 0);
|
||||
num_instances, base_instance);
|
||||
brw->prim_restart.enable_cut_index = false;
|
||||
} else {
|
||||
/* Not all the primitive draw modes are supported by the cut index,
|
||||
|
@@ -546,9 +546,7 @@ TAG(vbo_draw)(struct gl_context *ctx,
|
||||
const struct _mesa_index_buffer *ib,
|
||||
GLboolean index_bounds_valid,
|
||||
GLuint min_index, GLuint max_index,
|
||||
GLuint num_instances, GLuint base_instance,
|
||||
UNUSED struct gl_transform_feedback_object *tfb_vertcount,
|
||||
UNUSED unsigned stream)
|
||||
GLuint num_instances, GLuint base_instance)
|
||||
{
|
||||
/* Borrow and update the inputs list from the tnl context */
|
||||
const struct tnl_vertex_array* arrays = _tnl_bind_inputs(ctx);
|
||||
|
@@ -544,23 +544,13 @@ struct dd_function_table {
|
||||
* \param max_index highest vertex index used
|
||||
* \param num_instances instance count from ARB_draw_instanced
|
||||
* \param base_instance base instance from ARB_base_instance
|
||||
* \param tfb_vertcount if non-null, indicates which transform feedback
|
||||
* object has the vertex count.
|
||||
* \param tfb_stream If called via DrawTransformFeedbackStream, specifies
|
||||
* the vertex stream buffer from which to get the vertex
|
||||
* count.
|
||||
* \param indirect If any prims are indirect, this specifies the buffer
|
||||
* to find the "DrawArrays/ElementsIndirectCommand" data.
|
||||
* This may be deprecated in the future
|
||||
*/
|
||||
void (*Draw)(struct gl_context *ctx,
|
||||
const struct _mesa_prim *prims, GLuint nr_prims,
|
||||
const struct _mesa_index_buffer *ib,
|
||||
GLboolean index_bounds_valid,
|
||||
GLuint min_index, GLuint max_index,
|
||||
GLuint num_instances, GLuint base_instance,
|
||||
struct gl_transform_feedback_object *tfb_vertcount,
|
||||
unsigned tfb_stream);
|
||||
GLuint num_instances, GLuint base_instance);
|
||||
|
||||
|
||||
/**
|
||||
@@ -587,6 +577,21 @@ struct dd_function_table {
|
||||
struct gl_buffer_object *indirect_draw_count_buffer,
|
||||
GLsizeiptr indirect_draw_count_offset,
|
||||
const struct _mesa_index_buffer *ib);
|
||||
|
||||
/**
|
||||
* Driver implementation of glDrawTransformFeedback.
|
||||
*
|
||||
* \param mode Primitive type
|
||||
* \param num_instances instance count from ARB_draw_instanced
|
||||
* \param stream If called via DrawTransformFeedbackStream, specifies
|
||||
* the vertex stream buffer from which to get the vertex
|
||||
* count.
|
||||
* \param tfb_vertcount if non-null, indicates which transform feedback
|
||||
* object has the vertex count.
|
||||
*/
|
||||
void (*DrawTransformFeedback)(struct gl_context *ctx, GLenum mode,
|
||||
unsigned num_instances, unsigned stream,
|
||||
struct gl_transform_feedback_object *tfb_vertcount);
|
||||
/*@}*/
|
||||
|
||||
|
||||
|
@@ -366,7 +366,7 @@ _mesa_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start,
|
||||
|
||||
ctx->Driver.Draw(ctx, &prim, 1, NULL,
|
||||
GL_TRUE, start, start + count - 1,
|
||||
numInstances, baseInstance, NULL, 0);
|
||||
numInstances, baseInstance);
|
||||
|
||||
if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
|
||||
_mesa_flush(ctx);
|
||||
@@ -729,8 +729,7 @@ _mesa_exec_MultiDrawArrays(GLenum mode, const GLint *first,
|
||||
prim[i].basevertex = 0;
|
||||
}
|
||||
|
||||
ctx->Driver.Draw(ctx, prim, primcount, NULL, GL_FALSE, 0, 0, 1, 0,
|
||||
NULL, 0);
|
||||
ctx->Driver.Draw(ctx, prim, primcount, NULL, GL_FALSE, 0, 0, 1, 0);
|
||||
|
||||
if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
|
||||
_mesa_flush(ctx);
|
||||
@@ -890,7 +889,7 @@ _mesa_validated_drawrangeelements(struct gl_context *ctx, GLenum mode,
|
||||
|
||||
ctx->Driver.Draw(ctx, &prim, 1, &ib,
|
||||
index_bounds_valid, start, end,
|
||||
numInstances, baseInstance, NULL, 0);
|
||||
numInstances, baseInstance);
|
||||
|
||||
if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
|
||||
_mesa_flush(ctx);
|
||||
@@ -1312,7 +1311,7 @@ _mesa_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
|
||||
}
|
||||
|
||||
ctx->Driver.Draw(ctx, prim, primcount, &ib,
|
||||
false, 0, ~0, 1, 0, NULL, 0);
|
||||
false, 0, ~0, 1, 0);
|
||||
FREE_PRIMS(prim, primcount);
|
||||
}
|
||||
else {
|
||||
@@ -1337,7 +1336,7 @@ _mesa_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
|
||||
else
|
||||
prim.basevertex = 0;
|
||||
|
||||
ctx->Driver.Draw(ctx, &prim, 1, &ib, false, 0, ~0, 1, 0, NULL, 0);
|
||||
ctx->Driver.Draw(ctx, &prim, 1, &ib, false, 0, ~0, 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1412,8 +1411,6 @@ _mesa_draw_transform_feedback(struct gl_context *ctx, GLenum mode,
|
||||
struct gl_transform_feedback_object *obj,
|
||||
GLuint stream, GLuint numInstances)
|
||||
{
|
||||
struct _mesa_prim prim;
|
||||
|
||||
FLUSH_FOR_DRAW(ctx);
|
||||
|
||||
_mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
|
||||
@@ -1440,18 +1437,11 @@ _mesa_draw_transform_feedback(struct gl_context *ctx, GLenum mode,
|
||||
if (skip_validated_draw(ctx))
|
||||
return;
|
||||
|
||||
/* init most fields to zero */
|
||||
memset(&prim, 0, sizeof(prim));
|
||||
prim.begin = 1;
|
||||
prim.end = 1;
|
||||
prim.mode = mode;
|
||||
|
||||
/* Maybe we should do some primitive splitting for primitive restart
|
||||
* (like in DrawArrays), but we have no way to know how many vertices
|
||||
* will be rendered. */
|
||||
|
||||
ctx->Driver.Draw(ctx, &prim, 1, NULL, GL_FALSE, 0, ~0, numInstances, 0,
|
||||
obj, stream);
|
||||
ctx->Driver.DrawTransformFeedback(ctx, mode, numInstances, stream, obj);
|
||||
|
||||
if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
|
||||
_mesa_flush(ctx);
|
||||
|
@@ -260,8 +260,7 @@ st_RasterPos(struct gl_context *ctx, const GLfloat v[4])
|
||||
_mesa_set_draw_vao(ctx, rs->VAO, VERT_BIT_POS);
|
||||
|
||||
/* Draw the point. */
|
||||
st_feedback_draw_vbo(ctx, &rs->prim, 1, NULL, GL_TRUE, 0, 1, 1, 0,
|
||||
NULL, 0);
|
||||
st_feedback_draw_vbo(ctx, &rs->prim, 1, NULL, GL_TRUE, 0, 1, 1, 0);
|
||||
|
||||
/* restore draw's rasterization stage depending on rendermode */
|
||||
if (ctx->RenderMode == GL_FEEDBACK) {
|
||||
|
@@ -164,9 +164,7 @@ st_draw_vbo(struct gl_context *ctx,
|
||||
GLuint min_index,
|
||||
GLuint max_index,
|
||||
GLuint num_instances,
|
||||
GLuint base_instance,
|
||||
struct gl_transform_feedback_object *tfb_vertcount,
|
||||
unsigned stream)
|
||||
GLuint base_instance)
|
||||
{
|
||||
struct st_context *st = st_context(ctx);
|
||||
struct pipe_draw_info info;
|
||||
@@ -221,13 +219,6 @@ st_draw_vbo(struct gl_context *ctx,
|
||||
else {
|
||||
info.index_size = 0;
|
||||
info.has_user_indices = false;
|
||||
|
||||
/* Transform feedback drawing is always non-indexed. */
|
||||
/* Set info.count_from_stream_output. */
|
||||
if (tfb_vertcount) {
|
||||
if (!st_transform_feedback_draw_init(tfb_vertcount, stream, &info))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* do actual drawing */
|
||||
@@ -235,7 +226,7 @@ st_draw_vbo(struct gl_context *ctx,
|
||||
info.count = prims[i].count;
|
||||
|
||||
/* Skip no-op draw calls. */
|
||||
if (!info.count && !tfb_vertcount)
|
||||
if (!info.count)
|
||||
continue;
|
||||
|
||||
info.mode = translate_prim(ctx, prims[i].mode);
|
||||
@@ -332,12 +323,42 @@ st_indirect_draw_vbo(struct gl_context *ctx,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
st_draw_transform_feedback(struct gl_context *ctx, GLenum mode,
|
||||
unsigned num_instances, unsigned stream,
|
||||
struct gl_transform_feedback_object *tfb_vertcount)
|
||||
{
|
||||
struct st_context *st = st_context(ctx);
|
||||
struct pipe_draw_info info;
|
||||
|
||||
prepare_draw(st, ctx);
|
||||
|
||||
util_draw_init_info(&info);
|
||||
info.start = 0; /* index offset / index size */
|
||||
info.max_index = ~0u; /* so that u_vbuf can tell that it's unknown */
|
||||
info.mode = translate_prim(ctx, mode);
|
||||
info.vertices_per_patch = ctx->TessCtrlProgram.patch_vertices;
|
||||
info.instance_count = num_instances;
|
||||
|
||||
if (ST_DEBUG & DEBUG_DRAW) {
|
||||
debug_printf("st/draw transform feedback: mode %s\n",
|
||||
u_prim_name(info.mode));
|
||||
}
|
||||
|
||||
/* Transform feedback drawing is always non-indexed. */
|
||||
/* Set info.count_from_stream_output. */
|
||||
if (!st_transform_feedback_draw_init(tfb_vertcount, stream, &info))
|
||||
return;
|
||||
|
||||
cso_draw_vbo(st->cso_context, &info);
|
||||
}
|
||||
|
||||
void
|
||||
st_init_draw_functions(struct dd_function_table *functions)
|
||||
{
|
||||
functions->Draw = st_draw_vbo;
|
||||
functions->DrawIndirect = st_indirect_draw_vbo;
|
||||
functions->DrawTransformFeedback = st_draw_transform_feedback;
|
||||
}
|
||||
|
||||
|
||||
|
@@ -56,9 +56,7 @@ st_feedback_draw_vbo(struct gl_context *ctx,
|
||||
GLuint min_index,
|
||||
GLuint max_index,
|
||||
GLuint num_instances,
|
||||
GLuint base_instance,
|
||||
struct gl_transform_feedback_object *tfb_vertcount,
|
||||
unsigned stream);
|
||||
GLuint base_instance);
|
||||
|
||||
/**
|
||||
* When drawing with VBOs, the addresses specified with
|
||||
|
@@ -101,9 +101,7 @@ st_feedback_draw_vbo(struct gl_context *ctx,
|
||||
GLuint min_index,
|
||||
GLuint max_index,
|
||||
GLuint num_instances,
|
||||
GLuint base_instance,
|
||||
struct gl_transform_feedback_object *tfb_vertcount,
|
||||
unsigned stream)
|
||||
GLuint base_instance)
|
||||
{
|
||||
struct st_context *st = st_context(ctx);
|
||||
struct pipe_context *pipe = st->pipe;
|
||||
@@ -126,7 +124,6 @@ st_feedback_draw_vbo(struct gl_context *ctx,
|
||||
info.primitive_restart = false;
|
||||
info.vertices_per_patch = ctx->TessCtrlProgram.patch_vertices;
|
||||
info.indirect = NULL;
|
||||
info.count_from_stream_output = NULL;
|
||||
info.restart_index = 0;
|
||||
|
||||
st_flush_bitmap_cache(st);
|
||||
|
@@ -631,9 +631,7 @@ _tnl_draw(struct gl_context *ctx,
|
||||
const struct _mesa_prim *prim, GLuint nr_prims,
|
||||
const struct _mesa_index_buffer *ib,
|
||||
GLboolean index_bounds_valid, GLuint min_index, GLuint max_index,
|
||||
GLuint num_instances, GLuint base_instance,
|
||||
UNUSED struct gl_transform_feedback_object *tfb_vertcount,
|
||||
UNUSED unsigned stream)
|
||||
GLuint num_instances, GLuint base_instance)
|
||||
{
|
||||
/* Update TNLcontext::draw_arrays and return that pointer.
|
||||
*/
|
||||
|
@@ -115,8 +115,7 @@ _tnl_draw(struct gl_context *ctx,
|
||||
const struct _mesa_prim *prim, GLuint nr_prims,
|
||||
const struct _mesa_index_buffer *ib,
|
||||
GLboolean index_bounds_valid, GLuint min_index, GLuint max_index,
|
||||
GLuint num_instances, GLuint base_instance,
|
||||
struct gl_transform_feedback_object *tfb_vertcount, unsigned stream);
|
||||
GLuint num_instances, GLuint base_instance);
|
||||
|
||||
extern void
|
||||
_tnl_RasterPos(struct gl_context *ctx, const GLfloat vObj[4]);
|
||||
|
@@ -325,8 +325,7 @@ vbo_exec_vtx_flush(struct vbo_exec_context *exec)
|
||||
exec->vtx.vert_count);
|
||||
|
||||
ctx->Driver.Draw(ctx, exec->vtx.prim, exec->vtx.prim_count,
|
||||
NULL, GL_TRUE, 0, exec->vtx.vert_count - 1, 1, 0,
|
||||
NULL, 0);
|
||||
NULL, GL_TRUE, 0, exec->vtx.vert_count - 1, 1, 0);
|
||||
|
||||
/* Get new storage -- unless asked not to. */
|
||||
if (!persistent_mapping)
|
||||
|
@@ -254,13 +254,11 @@ vbo_sw_primitive_restart(struct gl_context *ctx,
|
||||
(temp_prim.count == sub_prim->count)) {
|
||||
ctx->Driver.Draw(ctx, &temp_prim, 1, ib, GL_TRUE,
|
||||
sub_prim->min_index, sub_prim->max_index,
|
||||
num_instances, base_instance,
|
||||
NULL, 0);
|
||||
num_instances, base_instance);
|
||||
} else {
|
||||
ctx->Driver.Draw(ctx, &temp_prim, 1, ib,
|
||||
GL_FALSE, -1, -1,
|
||||
num_instances, base_instance,
|
||||
NULL, 0);
|
||||
num_instances, base_instance);
|
||||
}
|
||||
}
|
||||
if (sub_end_index >= end_index) {
|
||||
|
@@ -213,7 +213,7 @@ vbo_save_playback_vertex_list(struct gl_context *ctx, void *data)
|
||||
GLuint min_index = _vbo_save_get_min_index(node);
|
||||
GLuint max_index = _vbo_save_get_max_index(node);
|
||||
ctx->Driver.Draw(ctx, node->prims, node->prim_count, NULL, GL_TRUE,
|
||||
min_index, max_index, 1, 0, NULL, 0);
|
||||
min_index, max_index, 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user