[virglrenderer-devel] [PATCH 3/3] renderer: add shader_storage_buffer_object support.
Gurchetan Singh
gurchetansingh at chromium.org
Wed Jul 18 00:11:47 UTC 2018
On Tue, Jul 17, 2018 at 12:48 AM Dave Airlie <airlied at gmail.com> wrote:
>
> From: Dave Airlie <airlied at redhat.com>
>
> This pulls the code out from the gles31 development,
> and modifies the caps to support two different limits
>
> (so far I've only found fs/cs vs everyone else limits differ)
> ---
> src/virgl_hw.h | 1 +
> src/virgl_protocol.h | 10 +++++
> src/vrend_decode.c | 33 ++++++++++++++
> src/vrend_renderer.c | 105 ++++++++++++++++++++++++++++++++++++++++++-
> src/vrend_renderer.h | 6 +++
> 5 files changed, 153 insertions(+), 2 deletions(-)
>
> diff --git a/src/virgl_hw.h b/src/virgl_hw.h
> index cd828ed..a85a14d 100644
> --- a/src/virgl_hw.h
> +++ b/src/virgl_hw.h
> @@ -307,6 +307,7 @@ struct virgl_caps_v2 {
> uint32_t capability_bits;
> uint32_t sample_locations[8];
> uint32_t max_vertex_attrib_stride;
> + uint32_t shader_storage_buffer_object_maximums; /* 0:15 bits for FS/CS; 16:31 bits for all other stages */
> };
>
> union virgl_caps {
> diff --git a/src/virgl_protocol.h b/src/virgl_protocol.h
> index a0b6984..6c73dfb 100644
> --- a/src/virgl_protocol.h
> +++ b/src/virgl_protocol.h
> @@ -85,6 +85,7 @@ enum virgl_context_cmd {
> VIRGL_CCMD_BIND_SHADER,
> VIRGL_CCMD_SET_TESS_STATE,
> VIRGL_CCMD_SET_MIN_SAMPLES,
> + VIRGL_CCMD_SET_SHADER_BUFFERS,
> };
>
> /*
> @@ -490,4 +491,13 @@ enum virgl_context_cmd {
> #define VIRGL_SET_MIN_SAMPLES_SIZE 1
> #define VIRGL_SET_MIN_SAMPLES_MASK 1
>
> +/* set shader buffers */
> +#define VIRGL_SET_SHADER_BUFFER_ELEMENT_SIZE 3
> +#define VIRGL_SET_SHADER_BUFFER_SIZE(x) (VIRGL_SET_SHADER_BUFFER_ELEMENT_SIZE * (x)) + 2
> +#define VIRGL_SET_SHADER_BUFFER_SHADER_TYPE 1
> +#define VIRGL_SET_SHADER_BUFFER_START_SLOT 2
> +#define VIRGL_SET_SHADER_BUFFER_OFFSET(x) ((x) * VIRGL_SET_SHADER_BUFFER_ELEMENT_SIZE + 2)
> +#define VIRGL_SET_SHADER_BUFFER_LENGTH(x) ((x) * VIRGL_SET_SHADER_BUFFER_ELEMENT_SIZE + 3)
> +#define VIRGL_SET_SHADER_BUFFER_RES_HANDLE(x) ((x) * VIRGL_SET_SHADER_BUFFER_ELEMENT_SIZE + 4)
> +
> #endif
> diff --git a/src/vrend_decode.c b/src/vrend_decode.c
> index 2432938..df516a0 100644
> --- a/src/vrend_decode.c
> +++ b/src/vrend_decode.c
> @@ -1077,6 +1077,36 @@ static int vrend_decode_set_tess_state(struct vrend_decode_ctx *ctx,
> return 0;
> }
>
> +static int vrend_decode_set_shader_buffers(struct vrend_decode_ctx *ctx, uint16_t length)
> +{
> + int num_ssbo;
> + uint32_t shader_type, start_slot;
> +
> + if (length < 2)
> + return EINVAL;
> +
> + num_ssbo = (length - 2) / VIRGL_SET_SHADER_BUFFER_ELEMENT_SIZE;
> + shader_type = get_buf_entry(ctx, VIRGL_SET_SHADER_BUFFER_SHADER_TYPE);
> + start_slot = get_buf_entry(ctx, VIRGL_SET_SHADER_BUFFER_START_SLOT);
> + if (shader_type >= PIPE_SHADER_TYPES)
> + return EINVAL;
> +
> + if (num_ssbo < 1)
> + return 0;
> +
> + if (start_slot + num_ssbo > PIPE_MAX_SHADER_BUFFERS)
> + return EINVAL;
> +
> + for (int i = 0; i < num_ssbo; i++) {
> + uint32_t offset = get_buf_entry(ctx, i * VIRGL_SET_SHADER_BUFFER_ELEMENT_SIZE + 3);
> + uint32_t buf_len = get_buf_entry(ctx, i * VIRGL_SET_SHADER_BUFFER_ELEMENT_SIZE + 4);
> + uint32_t handle = get_buf_entry(ctx, i * VIRGL_SET_SHADER_BUFFER_ELEMENT_SIZE + 5);
> + vrend_set_single_ssbo(ctx->grctx, shader_type, start_slot + i, offset, buf_len,
> + handle);
> + }
> + return 0;
> +}
> +
> static int vrend_decode_set_streamout_targets(struct vrend_decode_ctx *ctx,
> uint16_t length)
> {
> @@ -1305,6 +1335,9 @@ int vrend_decode_block(uint32_t ctx_id, uint32_t *block, int ndw)
> case VIRGL_CCMD_SET_TESS_STATE:
> ret = vrend_decode_set_tess_state(gdctx, len);
> break;
> + case VIRGL_CCMD_SET_SHADER_BUFFERS:
> + ret = vrend_decode_set_shader_buffers(gdctx, len);
> + break;
> default:
> ret = EINVAL;
> }
> diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c
> index 69f1da3..ce4d744 100644
> --- a/src/vrend_renderer.c
> +++ b/src/vrend_renderer.c
> @@ -119,6 +119,7 @@ struct global_renderer_state {
> bool have_texture_storage;
> bool have_tessellation;
> bool have_texture_view;
> + bool have_ssbo;
>
> /* these appeared broken on at least one driver */
> bool use_explicit_locations;
> @@ -166,6 +167,9 @@ struct vrend_linked_shader_program {
> GLint fs_stipple_loc;
>
> GLuint clip_locs[8];
> +
> + uint32_t ssbo_used_mask[PIPE_SHADER_TYPES];
> + GLuint *ssbo_locs[PIPE_SHADER_TYPES];
> };
>
> struct vrend_shader {
> @@ -243,6 +247,12 @@ struct vrend_sampler_view {
> struct vrend_resource *texture;
> };
>
> +struct vrend_ssbo {
> + struct vrend_resource *res;
> + unsigned buffer_size;
> + unsigned buffer_offset;
> +};
> +
> struct vrend_vertex_element {
> struct pipe_vertex_element base;
> GLenum type;
> @@ -381,6 +391,9 @@ struct vrend_sub_context {
>
> uint32_t cond_render_q_id;
> GLenum cond_render_gl_mode;
> +
> + struct vrend_ssbo ssbo[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_BUFFERS];
> + uint32_t ssbo_used_mask[PIPE_SHADER_TYPES];
> };
>
> struct vrend_context {
> @@ -951,6 +964,29 @@ static void bind_ubo_locs(struct vrend_linked_shader_program *sprog,
> sprog->ubo_locs[id] = NULL;
> }
>
> +static void bind_ssbo_locs(struct vrend_linked_shader_program *sprog,
> + int id)
> +{
> + int i;
> + char name[32];
> + if (sprog->ss[id]->sel->sinfo.ssbo_used_mask) {
> + const char *prefix = pipe_shader_to_prefix(id);
> + uint32_t mask = sprog->ss[id]->sel->sinfo.ssbo_used_mask;
> + sprog->ssbo_locs[id] = calloc(util_last_bit(mask), sizeof(uint32_t));
> +
> + while (mask) {
> + i = u_bit_scan(&mask);
> + if (0)//sprog->ss[id]->sel->sinfo.ssbo_indirect)
> + snprintf(name, 32, "%sssbo[%d]", prefix, i);
nit: if (0) case looks useless
Other than that, this series is:
Reviewed-by: Gurchetan Singh <gurchetansingh at chromium.org>
> + else
> + snprintf(name, 32, "%sssbo%d", prefix, i);
> + sprog->ssbo_locs[id][i] = glGetProgramResourceIndex(sprog->id, GL_SHADER_STORAGE_BLOCK, name);
> + }
> + } else
> + sprog->ssbo_locs[id] = NULL;
> + sprog->ssbo_used_mask[id] = sprog->ss[id]->sel->sinfo.ssbo_used_mask;
> +}
> +
> static struct vrend_linked_shader_program *add_shader_program(struct vrend_context *ctx,
> struct vrend_shader *vs,
> struct vrend_shader *fs,
> @@ -1096,6 +1132,7 @@ static struct vrend_linked_shader_program *add_shader_program(struct vrend_conte
> bind_sampler_locs(sprog, id);
> bind_const_locs(sprog, id);
> bind_ubo_locs(sprog, id);
> + bind_ssbo_locs(sprog, id);
> }
>
> if (!vrend_state.have_gles31_vertex_attrib_binding) {
> @@ -2255,6 +2292,32 @@ void vrend_set_num_sampler_views(struct vrend_context *ctx,
> ctx->sub->views[shader_type].num_views = last_slot;
> }
>
> +void vrend_set_single_ssbo(struct vrend_context *ctx,
> + uint32_t shader_type,
> + int index,
> + uint32_t offset, uint32_t length,
> + uint32_t handle)
> +{
> + struct vrend_ssbo *ssbo = &ctx->sub->ssbo[shader_type][index];
> + struct vrend_resource *res;
> + if (handle) {
> + res = vrend_renderer_ctx_res_lookup(ctx, handle);
> + if (!res) {
> + report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, handle);
> + return;
> + }
> + ssbo->buffer_offset = offset;
> + ssbo->buffer_size = length;
> + ssbo->res = res;
> + ctx->sub->ssbo_used_mask[shader_type] |= (1 << index);
> + } else {
> + ssbo->res = 0;
> + ssbo->buffer_offset = 0;
> + ssbo->buffer_size = 0;
> + ctx->sub->ssbo_used_mask[shader_type] &= ~(1 << index);
> + }
> +}
> +
> static void vrend_destroy_shader_object(void *obj_ptr)
> {
> struct vrend_shader_selector *state = obj_ptr;
> @@ -3148,6 +3211,31 @@ static void vrend_draw_bind_const_shader(struct vrend_context *ctx,
> }
> }
>
> +static void vrend_draw_bind_ssbo_shader(struct vrend_context *ctx, int shader_type)
> +{
> + uint32_t mask;
> + struct vrend_ssbo *ssbo;
> + struct vrend_resource *res;
> + int i;
> +
> + if (!ctx->sub->prog->ssbo_locs[shader_type])
> + return;
> +
> + if (!ctx->sub->ssbo_used_mask[shader_type])
> + return;
> +
> + mask = ctx->sub->ssbo_used_mask[shader_type];
> + while (mask) {
> + i = u_bit_scan(&mask);
> +
> + ssbo = &ctx->sub->ssbo[shader_type][i];
> + res = (struct vrend_resource *)ssbo->res;
> + glBindBufferRange(GL_SHADER_STORAGE_BUFFER, i, res->id,
> + ssbo->buffer_offset, ssbo->buffer_size);
> + glShaderStorageBlockBinding(ctx->sub->prog->id, ctx->sub->prog->ssbo_locs[shader_type][i], i);
> + }
> +}
> +
> static void vrend_draw_bind_objects(struct vrend_context *ctx, bool new_program)
> {
> int ubo_id = 0, sampler_id = 0;
> @@ -3155,6 +3243,7 @@ static void vrend_draw_bind_objects(struct vrend_context *ctx, bool new_program)
> vrend_draw_bind_ubo_shader(ctx, shader_type, &ubo_id);
> vrend_draw_bind_const_shader(ctx, shader_type, new_program);
> vrend_draw_bind_samplers_shader(ctx, shader_type, &sampler_id);
> + vrend_draw_bind_ssbo_shader(ctx, shader_type);
> }
>
> if (vrend_state.use_core_profile && ctx->sub->prog->fs_stipple_loc != -1) {
> @@ -4553,6 +4642,9 @@ int vrend_renderer_init(struct vrend_if_cbs *cbs, uint32_t flags)
> if (gl_ver >= 43 || epoxy_has_gl_extension("GL_ARB_texture_view"))
> vrend_state.have_texture_view = true;
>
> + if (gl_ver >= 43 || epoxy_has_gl_extension("GL_ARB_shader_storage_buffer_object"))
> + vrend_state.have_ssbo = true;
> +
> if (gl_ver >= 46 || epoxy_has_gl_extension("GL_ARB_polygon_offset_clamp"))
> vrend_state.have_polygon_offset_clamp = true;
>
> @@ -4853,7 +4945,8 @@ static int check_resource_valid(struct vrend_renderer_resource_create_args *args
> args->bind == VREND_RES_BIND_INDEX_BUFFER ||
> args->bind == VREND_RES_BIND_STREAM_OUTPUT ||
> args->bind == VREND_RES_BIND_VERTEX_BUFFER ||
> - args->bind == VREND_RES_BIND_CONSTANT_BUFFER) {
> + args->bind == VREND_RES_BIND_CONSTANT_BUFFER ||
> + args->bind == VREND_RES_BIND_SHADER_BUFFER) {
> if (args->target != PIPE_BUFFER)
> return -1;
> if (args->height != 1 || args->depth != 1)
> @@ -5094,7 +5187,7 @@ int vrend_renderer_resource_create(struct vrend_renderer_resource_create_args *a
> } else if (args->target == PIPE_BUFFER && args->bind == 0) {
> gr->target = GL_ARRAY_BUFFER_ARB;
> vrend_create_buffer(gr, args->width);
> - } else if (args->target == PIPE_BUFFER && (args->bind & VREND_RES_BIND_SAMPLER_VIEW)) {
> + } else if (args->target == PIPE_BUFFER && (args->bind == 0 || args->bind == VREND_RES_BIND_SHADER_BUFFER)) {
> /*
> * On Desktop we use GL_ARB_texture_buffer_object on GLES we use
> * GL_EXT_texture_buffer (it is in the ANDRIOD extension pack).
> @@ -7579,7 +7672,15 @@ void vrend_renderer_fill_caps(uint32_t set, uint32_t version,
>
> if (gl_ver >= 43) {
> glGetIntegerv(GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT, (GLint*)&caps->v2.texture_buffer_offset_alignment);
> + }
> +
> + if (gl_ver >= 43 || epoxy_has_gl_extension("GL_ARB_shader_storage_buffer_object")) {
> glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, (GLint*)&caps->v2.shader_buffer_offset_alignment);
> +
> + glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &max);
> + caps->v2.shader_storage_buffer_object_maximums = (max << 16);
> + glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &max);
> + caps->v2.shader_storage_buffer_object_maximums |= max & 0xffff;
> }
>
> caps->v1.max_samples = vrend_renderer_query_multisample_caps(max, &caps->v2);
> diff --git a/src/vrend_renderer.h b/src/vrend_renderer.h
> index b2c2fd8..a3160bb 100644
> --- a/src/vrend_renderer.h
> +++ b/src/vrend_renderer.h
> @@ -154,6 +154,7 @@ void vrend_renderer_context_destroy(uint32_t handle);
> #define VREND_RES_BIND_INDEX_BUFFER (1 << 5)
> #define VREND_RES_BIND_CONSTANT_BUFFER (1 << 6)
> #define VREND_RES_BIND_STREAM_OUTPUT (1 << 11)
> +#define VREND_RES_BIND_SHADER_BUFFER (1 << 14)
> #define VREND_RES_BIND_CURSOR (1 << 16)
> #define VREND_RES_BIND_CUSTOM (1 << 17)
>
> @@ -246,6 +247,11 @@ void vrend_set_index_buffer(struct vrend_context *ctx,
> uint32_t res_handle,
> uint32_t index_size,
> uint32_t offset);
> +void vrend_set_single_ssbo(struct vrend_context *ctx,
> + uint32_t shader_type,
> + int index,
> + uint32_t offset, uint32_t length,
> + uint32_t handle);
>
> #define VREND_TRANSFER_WRITE 1
> #define VREND_TRANSFER_READ 2
> --
> 2.17.1
>
> _______________________________________________
> virglrenderer-devel mailing list
> virglrenderer-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/virglrenderer-devel
More information about the virglrenderer-devel
mailing list