diff options
author | Dave Airlie <airlied@gmail.com> | 2015-03-18 18:27:25 +1000 |
---|---|---|
committer | Dave Airlie <airlied@gmail.com> | 2015-03-18 18:27:25 +1000 |
commit | c0822de483d88704ef7d2c97c94703f2366145a5 (patch) | |
tree | e77f8eeddb3a4fb5372b8a3303660d06c28684a2 | |
parent | c89bb9c5f9033e7f766867621c9f1c13aa669596 (diff) |
streamout: WIP getting there slowlyso-wip
-rw-r--r-- | src/virgl_protocol.h | 6 | ||||
-rw-r--r-- | src/vrend_decode.c | 14 | ||||
-rw-r--r-- | src/vrend_renderer.c | 99 | ||||
-rw-r--r-- | src/vrend_renderer.h | 4 |
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); |