summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@gmail.com>2015-03-18 18:27:25 +1000
committerDave Airlie <airlied@gmail.com>2015-03-18 18:27:25 +1000
commitc0822de483d88704ef7d2c97c94703f2366145a5 (patch)
treee77f8eeddb3a4fb5372b8a3303660d06c28684a2
parentc89bb9c5f9033e7f766867621c9f1c13aa669596 (diff)
streamout: WIP getting there slowlyso-wip
-rw-r--r--src/virgl_protocol.h6
-rw-r--r--src/vrend_decode.c14
-rw-r--r--src/vrend_renderer.c99
-rw-r--r--src/vrend_renderer.h4
4 files changed, 80 insertions, 43 deletions
diff --git a/src/virgl_protocol.h b/src/virgl_protocol.h
index c6704e0..33d43e1 100644
--- a/src/virgl_protocol.h
+++ b/src/virgl_protocol.h
@@ -246,7 +246,7 @@ enum virgl_context_cmd {
#define VIRGL_SET_UNIFORM_BUFFER_RES_HANDLE 5
/* draw VBO */
-#define VIRGL_DRAW_VBO_SIZE 11
+#define VIRGL_DRAW_VBO_SIZE 12
#define VIRGL_DRAW_VBO_START 1
#define VIRGL_DRAW_VBO_COUNT 2
#define VIRGL_DRAW_VBO_MODE 3
@@ -258,6 +258,7 @@ enum virgl_context_cmd {
#define VIRGL_DRAW_VBO_RESTART_INDEX 9
#define VIRGL_DRAW_VBO_MIN_INDEX 10
#define VIRGL_DRAW_VBO_MAX_INDEX 11
+#define VIRGL_DRAW_VBO_COUNT_FROM_SO 12
/* create surface */
#define VIRGL_OBJ_SURFACE_SIZE 5
@@ -416,7 +417,8 @@ enum virgl_context_cmd {
/* set streamout targets */
#define VIRGL_SET_STREAMOUT_TARGETS_APPEND_BITMASK 1
-#define VIRGL_SET_STREAMOUT_TARGETS_H0 2
+#define VIRGL_SET_STREAMOUT_TARGETS_FLAGS 2
+#define VIRGL_SET_STREAMOUT_TARGETS_H0 3
/* set sample mask */
#define VIRGL_SET_SAMPLE_MASK_SIZE 1
diff --git a/src/vrend_decode.c b/src/vrend_decode.c
index 1da942c..26b4a30 100644
--- a/src/vrend_decode.c
+++ b/src/vrend_decode.c
@@ -343,7 +343,7 @@ static int vrend_decode_resource_inline_write(struct vrend_decode_ctx *ctx, uint
static int vrend_decode_draw_vbo(struct vrend_decode_ctx *ctx, int length)
{
struct pipe_draw_info info;
-
+ uint32_t cso;
if (length != VIRGL_DRAW_VBO_SIZE)
return EINVAL;
memset(&info, 0, sizeof(struct pipe_draw_info));
@@ -359,7 +359,10 @@ static int vrend_decode_draw_vbo(struct vrend_decode_ctx *ctx, int length)
info.restart_index = get_buf_entry(ctx, VIRGL_DRAW_VBO_RESTART_INDEX);
info.min_index = get_buf_entry(ctx, VIRGL_DRAW_VBO_MIN_INDEX);
info.max_index = get_buf_entry(ctx, VIRGL_DRAW_VBO_MAX_INDEX);
- vrend_draw_vbo(ctx->grctx, &info);
+
+ cso = get_buf_entry(ctx, VIRGL_DRAW_VBO_COUNT_FROM_SO);
+
+ vrend_draw_vbo(ctx->grctx, &info, cso);
return 0;
}
@@ -994,16 +997,17 @@ static int vrend_decode_set_streamout_targets(struct vrend_decode_ctx *ctx,
uint16_t length)
{
uint32_t handles[16];
- uint32_t num_handles = length - 1;
- uint32_t append_bitmask;
+ uint32_t num_handles = length - 2;
+ uint32_t append_bitmask, flags;
int i;
if (length < 1)
return EINVAL;
append_bitmask = get_buf_entry(ctx, VIRGL_SET_STREAMOUT_TARGETS_APPEND_BITMASK);
+ flags = get_buf_entry(ctx, VIRGL_SET_STREAMOUT_TARGETS_FLAGS);
for (i = 0; i < num_handles; i++)
handles[i] = get_buf_entry(ctx, VIRGL_SET_STREAMOUT_TARGETS_H0 + i);
- vrend_set_streamout_targets(ctx->grctx, append_bitmask, num_handles, handles);
+ vrend_set_streamout_targets(ctx->grctx, append_bitmask, flags,num_handles, handles);
return 0;
}
diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c
index b27db9b..654f198 100644
--- a/src/vrend_renderer.c
+++ b/src/vrend_renderer.c
@@ -246,6 +246,15 @@ struct vrend_viewport {
GLclampd near_val, far_val;
};
+/* create a streamout object to support pause/resume */
+struct vrend_streamout_object {
+ GLuint id;
+ uint32_t num_targets;
+ uint32_t handles[16];
+ struct list_head head;
+ struct vrend_so_target *so_targets[16];
+};
+
#define XFB_STATE_OFF 0
#define XFB_STATE_STARTED_NEED_BEGIN 1
#define XFB_STATE_STARTED 2
@@ -313,8 +322,11 @@ struct vrend_sub_context {
struct pipe_depth_stencil_alpha_state dsa_state;
struct pipe_rasterizer_state rs_state;
+ /* number in use - 0 for paused */
int num_so_targets;
- struct vrend_so_target *so_targets[16];
+ /* number of bounds */
+ int bound_so_targets;
+
uint8_t stencil_refs[2];
@@ -334,6 +346,8 @@ struct vrend_sub_context {
struct pipe_blend_state hw_blend_state;
int xfb_state;
+
+ struct list_head streamout_list;
};
struct vrend_context {
@@ -2091,7 +2105,8 @@ static GLenum get_xfb_mode(GLenum mode)
}
void vrend_draw_vbo(struct vrend_context *ctx,
- const struct pipe_draw_info *info)
+ const struct pipe_draw_info *info,
+ uint32_t cso)
{
int i;
int sampler_id;
@@ -2400,12 +2415,14 @@ void vrend_draw_vbo(struct vrend_context *ctx,
/* set the vertex state up now on a delay */
if (!info->indexed) {
GLenum mode = info->mode;
+ int count = cso ? cso : info->count;
+ int start = cso ? 0 : info->start;
if (info->instance_count <= 1)
- glDrawArrays(mode, info->start, info->count);
+ glDrawArrays(mode, start, count);
else if (info->start_instance)
- glDrawArraysInstancedBaseInstance(mode, info->start, info->count, info->instance_count, info->start_instance);
+ glDrawArraysInstancedBaseInstance(mode, start, count, info->instance_count, info->start_instance);
else
- glDrawArraysInstancedARB(mode, info->start, info->count, info->instance_count);
+ glDrawArraysInstancedARB(mode, start, count, info->instance_count);
} else {
GLenum elsz;
GLenum mode = info->mode;
@@ -3289,7 +3306,7 @@ bool vrend_destroy_context(struct vrend_context *ctx)
vrend_set_num_sampler_views(ctx, PIPE_SHADER_FRAGMENT, 0, 0);
vrend_set_num_sampler_views(ctx, PIPE_SHADER_GEOMETRY, 0, 0);
- vrend_set_streamout_targets(ctx, 0, 0, NULL);
+ vrend_set_streamout_targets(ctx, 0, 0, 0, NULL);
vrend_set_num_vbo(ctx, 0);
vrend_set_index_buffer(ctx, 0, 0, 0);
@@ -4424,54 +4441,64 @@ void vrend_set_sample_mask(struct vrend_context *ctx, unsigned sample_mask)
}
-static void vrend_hw_emit_streamout_targets(struct vrend_context *ctx)
+static void vrend_hw_emit_streamout_targets(struct vrend_context *ctx, struct vrend_streamout_object *so_obj)
{
int i;
- for (i = 0; i < ctx->sub->num_so_targets; i++) {
- if (ctx->sub->so_targets[i]->buffer_offset || ctx->sub->so_targets[i]->buffer_size < ctx->sub->so_targets[i]->buffer->base.width0)
- glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, i, ctx->sub->so_targets[i]->buffer->id, ctx->sub->so_targets[i]->buffer_offset, ctx->sub->so_targets[i]->buffer_size);
+ for (i = 0; i < so_obj->num_targets; i++) {
+ if (so_obj->so_targets[i]->buffer_offset || so_obj->so_targets[i]->buffer_size < so_obj->so_targets[i]->buffer->base.width0)
+ glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, i, so_obj->so_targets[i]->buffer->id, so_obj->so_targets[i]->buffer_offset, so_obj->so_targets[i]->buffer_size);
else
- glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, i, ctx->sub->so_targets[i]->buffer->id);
+ glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, i, so_obj->so_targets[i]->buffer->id);
}
}
void vrend_set_streamout_targets(struct vrend_context *ctx,
uint32_t append_bitmask,
+ uint32_t flags,
uint32_t num_targets,
uint32_t *handles)
{
struct vrend_so_target *target;
int i;
- int old_num = ctx->sub->num_so_targets;
-
- ctx->sub->num_so_targets = num_targets;
-
- if (num_targets == 0 && (ctx->sub->xfb_state == XFB_STATE_STARTED || ctx->sub->xfb_state == XFB_STATE_PAUSED)) {
- glEndTransformFeedback();
- ctx->sub->xfb_state = XFB_STATE_OFF;
- }
-
- for (i = 0; i < num_targets; i++) {
- target = vrend_object_lookup(ctx->sub->object_hash, handles[i], VIRGL_OBJECT_STREAMOUT_TARGET);
- if (!target) {
- report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_HANDLE, handles[i]);
- return;
+ int old_num = ctx->sub->bound_so_targets;
+ bool new_buffers = false;
+
+ if (num_targets) {
+ bool found = false;
+ struct vrend_streamout_object *obj;
+ LIST_FOR_EACH_ENTRY(obj, &ctx->sub->streamout_list, head) {
+ if (obj->num_targets == num_targets) {
+ if (!memcmp(handles, obj->handles, num_targets * 4)) {
+ found = true;
+ break;
+ }
+ }
+ }
+ if (found) {
+ glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, obj->id);
+ return;
}
- vrend_so_target_reference(&ctx->sub->so_targets[i], target);
- }
- for (i = num_targets; i < old_num; i++) {
- glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, i, 0);
- vrend_so_target_reference(&ctx->sub->so_targets[i], NULL);
+ obj = CALLOC_STRUCT(vrend_streamout_object);
+ glGenTransformFeedbacks(1, &obj->id);
+ glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, obj->id);
+ obj->num_targets = num_targets;
+ for (i = 0; i < num_targets; i++) {
+ obj->handles[i] = handles[i];
+ target = vrend_object_lookup(ctx->sub->object_hash, handles[i], VIRGL_OBJECT_STREAMOUT_TARGET);
+ if (!target) {
+ report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_HANDLE, handles[i]);
+ return;
+ }
+ vrend_so_target_reference(&obj->so_targets[i], target);
+ }
+ vrend_hw_emit_streamout_targets(ctx, obj);
+ list_addtail(&obj->head, &ctx->sub->streamout_list);
}
- vrend_hw_emit_streamout_targets(ctx);
-
- if (ctx->sub->num_so_targets) {
- if (ctx->sub->xfb_state == XFB_STATE_OFF)
+ if (ctx->sub->xfb_state == XFB_STATE_OFF && num_targets)
ctx->sub->xfb_state = XFB_STATE_STARTED_NEED_BEGIN;
- }
}
@@ -5566,6 +5593,8 @@ void vrend_renderer_create_sub_ctx(struct vrend_context *ctx, int sub_ctx_id)
glGenFramebuffers(2, sub->blit_fb_ids);
list_inithead(&sub->programs);
+ list_inithead(&sub->streamout_list);
+
sub->object_hash = vrend_object_init_ctx_table();
vrend_bind_va(sub->vaoid);
diff --git a/src/vrend_renderer.h b/src/vrend_renderer.h
index a08aa8e..8eff9fa 100644
--- a/src/vrend_renderer.h
+++ b/src/vrend_renderer.h
@@ -124,7 +124,8 @@ void vrend_clear(struct vrend_context *ctx,
double depth, unsigned stencil);
void vrend_draw_vbo(struct vrend_context *ctx,
- const struct pipe_draw_info *info);
+ const struct pipe_draw_info *info,
+ uint32_t cso);
void vrend_set_framebuffer_state(struct vrend_context *ctx,
uint32_t nr_cbufs, uint32_t surf_handle[8],
@@ -191,6 +192,7 @@ int vrend_create_so_target(struct vrend_context *ctx,
void vrend_set_streamout_targets(struct vrend_context *ctx,
uint32_t append_bitmask,
+ uint32_t flags,
uint32_t num_targets,
uint32_t *handles);