From 5e89aea8883059b03661a27683d8cea084801aee Mon Sep 17 00:00:00 2001 From: Erik Faye-Lund Date: Mon, 14 Jan 2019 23:40:10 +0100 Subject: [PATCH] virglrenderer: use bitmask instead of arrays of indices We already track samplers, images and ssbos using bitmasks, so this is a bit more familiar to the rest of the code. Also, this is going to enable some other nifty optimizations later on. Reviewed-by: Gurchetan Singh Signed-off-by: Erik Faye-Lund Signed-off-by: Jakob Bornecrantz --- src/vrend_renderer.c | 29 +++++++++-------------------- src/vrend_shader.c | 33 +++++++++++++++++++-------------- src/vrend_shader.h | 3 +-- 3 files changed, 29 insertions(+), 36 deletions(-) diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c index 1c29d6b..f8ccb83 100644 --- a/src/vrend_renderer.c +++ b/src/vrend_renderer.c @@ -289,7 +289,7 @@ struct vrend_linked_shader_program { GLuint *attrib_locs; uint32_t shadow_samp_mask[PIPE_SHADER_TYPES]; - GLuint *ubo_locs[PIPE_SHADER_TYPES]; + GLuint ubo_locs[PIPE_SHADER_TYPES][32]; GLuint vs_ws_adjust_loc; float viewport_neg_val; @@ -1135,22 +1135,21 @@ static void bind_ubo_locs(struct vrend_linked_shader_program *sprog, { if (!has_feature(feat_ubo)) return; - if (sprog->ss[id]->sel->sinfo.num_ubos) { + if (sprog->ss[id]->sel->sinfo.ubo_used_mask) { const char *prefix = pipe_shader_to_prefix(id); - sprog->ubo_locs[id] = calloc(sprog->ss[id]->sel->sinfo.num_ubos, sizeof(uint32_t)); - for (int i = 0; i < sprog->ss[id]->sel->sinfo.num_ubos; i++) { - int ubo_idx = sprog->ss[id]->sel->sinfo.ubo_idx[i]; + unsigned mask = sprog->ss[id]->sel->sinfo.ubo_used_mask; + while (mask) { + uint32_t ubo_idx = u_bit_scan(&mask); char name[32]; if (sprog->ss[id]->sel->sinfo.ubo_indirect) snprintf(name, 32, "%subo[%d]", prefix, ubo_idx - 1); else snprintf(name, 32, "%subo%d", prefix, ubo_idx); - sprog->ubo_locs[id][i] = glGetUniformBlockIndex(sprog->id, name); + sprog->ubo_locs[id][ubo_idx] = glGetUniformBlockIndex(sprog->id, name); } - } else - sprog->ubo_locs[id] = NULL; + } } static void bind_ssbo_locs(struct vrend_linked_shader_program *sprog, @@ -1492,7 +1491,6 @@ static void vrend_destroy_program(struct vrend_linked_shader_program *ent) free(ent->samp_locs[i]); free(ent->ssbo_locs[i]); free(ent->img_locs[i]); - free(ent->ubo_locs[i]); } free(ent->attrib_locs); free(ent); @@ -3647,7 +3645,6 @@ static void vrend_draw_bind_ubo_shader(struct vrend_context *ctx, int shader_type, int *ubo_id) { uint32_t mask; - int shader_ubo_idx; struct pipe_constant_buffer *cb; struct vrend_resource *res; struct vrend_shader_info* sinfo; @@ -3663,7 +3660,7 @@ static void vrend_draw_bind_ubo_shader(struct vrend_context *ctx, sinfo = &ctx->sub->prog->ss[shader_type]->sel->sinfo; - mask = ctx->sub->const_bufs_used_mask[shader_type]; + mask = ctx->sub->const_bufs_used_mask[shader_type] & sinfo->ubo_used_mask; while (mask) { /* The const_bufs_used_mask stores the gallium uniform buffer indices */ int i = u_bit_scan(&mask); @@ -3672,18 +3669,10 @@ static void vrend_draw_bind_ubo_shader(struct vrend_context *ctx, cb = &ctx->sub->cbs[shader_type][i]; res = (struct vrend_resource *)cb->buffer; - /* Find the index of the uniform buffer in the array of shader ubo data */ - for (shader_ubo_idx = 0; shader_ubo_idx < sinfo->num_ubos; shader_ubo_idx++) { - if (sinfo->ubo_idx[shader_ubo_idx] == i) - break; - } - if (shader_ubo_idx == sinfo->num_ubos) - continue; - glBindBufferRange(GL_UNIFORM_BUFFER, *ubo_id, res->id, cb->buffer_offset, cb->buffer_size); /* The ubo_locs array is indexed using the shader ubo index */ - glUniformBlockBinding(ctx->sub->prog->id, ctx->sub->prog->ubo_locs[shader_type][shader_ubo_idx], *ubo_id); + glUniformBlockBinding(ctx->sub->prog->id, ctx->sub->prog->ubo_locs[shader_type][i], *ubo_id); (*ubo_id)++; } } diff --git a/src/vrend_shader.c b/src/vrend_shader.c index 09d354c..7d8d0eb 100644 --- a/src/vrend_shader.c +++ b/src/vrend_shader.c @@ -178,9 +178,8 @@ struct dump_ctx { uint32_t req_local_mem; bool integer_memory; - uint32_t num_ubo; uint32_t ubo_base; - int ubo_idx[32]; + uint32_t ubo_used_mask; int ubo_sizes[32]; uint32_t num_address; @@ -1240,13 +1239,16 @@ iter_declaration(struct tgsi_iterate_context *iter, break; case TGSI_FILE_CONSTANT: if (decl->Declaration.Dimension && decl->Dim.Index2D != 0) { - if (ctx->num_ubo >= ARRAY_SIZE(ctx->ubo_idx)) { - fprintf(stderr, "Number of uniforms exceeded, max is %lu\n", ARRAY_SIZE(ctx->ubo_idx)); + if (decl->Dim.Index2D > 31) { + fprintf(stderr, "Number of uniforms exceeded, max is 32\n"); return false; } - ctx->ubo_idx[ctx->num_ubo] = decl->Dim.Index2D; - ctx->ubo_sizes[ctx->num_ubo] = decl->Range.Last + 1; - ctx->num_ubo++; + if (ctx->ubo_used_mask & (1 << decl->Dim.Index2D)) { + fprintf(stderr, "UBO #%d is already defined\n", decl->Dim.Index2D); + return false; + } + ctx->ubo_used_mask |= (1 << decl->Dim.Index2D); + ctx->ubo_sizes[decl->Dim.Index2D] = decl->Range.Last + 1; } else { /* if we have a normal single const set then ubo base should be 1 */ ctx->ubo_base = 1; @@ -3927,7 +3929,7 @@ static void emit_header(struct dump_ctx *ctx) if (ctx->prog_type == TGSI_PROCESSOR_FRAGMENT && fs_emit_layout(ctx)) emit_ext(ctx, "ARB_fragment_coord_conventions", "require"); - if (ctx->num_ubo) + if (ctx->ubo_used_mask) emit_ext(ctx, "ARB_uniform_buffer_object", "require"); if (ctx->num_cull_dist_prop || ctx->key->prev_stage_num_cull_out) @@ -4601,15 +4603,19 @@ static void emit_ios(struct dump_ctx *ctx) if (ctx->color_in_mask & 2) emit_hdr(ctx, "vec4 realcolor1;\n"); } - if (ctx->num_ubo) { + if (ctx->ubo_used_mask) { const char *cname = tgsi_proc_to_prefix(ctx->prog_type); if (ctx->info.dimension_indirect_files & (1 << TGSI_FILE_CONSTANT)) { require_glsl_ver(ctx, 150); - emit_hdrf(ctx, "uniform %subo { vec4 ubocontents[%d]; } %suboarr[%d];\n", cname, ctx->ubo_sizes[0], cname, ctx->num_ubo); + int first = ffs(ctx->ubo_used_mask) - 1; + unsigned num_ubo = util_bitcount(ctx->ubo_used_mask); + emit_hdrf(ctx, "uniform %subo { vec4 ubocontents[%d]; } %suboarr[%d];\n", cname, ctx->ubo_sizes[first], cname, num_ubo); } else { - for (i = 0; i < ctx->num_ubo; i++) { - emit_hdrf(ctx, "uniform %subo%d { vec4 %subo%dcontents[%d]; };\n", cname, ctx->ubo_idx[i], cname, ctx->ubo_idx[i], ctx->ubo_sizes[i]); + unsigned mask = ctx->ubo_used_mask; + while (mask) { + uint32_t i = u_bit_scan(&mask); + emit_hdrf(ctx, "uniform %subo%d { vec4 %subo%dcontents[%d]; };\n", cname, i, cname, i, ctx->ubo_sizes[i]); } } } @@ -4847,8 +4853,7 @@ char *vrend_convert_shader(struct vrend_context *rctx, sinfo->samplers_used_mask = ctx.samplers_used; sinfo->images_used_mask = ctx.images_used_mask; sinfo->num_consts = ctx.num_consts; - sinfo->num_ubos = ctx.num_ubo; - memcpy(sinfo->ubo_idx, ctx.ubo_idx, ctx.num_ubo * sizeof(*ctx.ubo_idx)); + sinfo->ubo_used_mask = ctx.ubo_used_mask; sinfo->ssbo_used_mask = ctx.ssbo_used_mask; diff --git a/src/vrend_shader.h b/src/vrend_shader.h index cb928e6..a1a5744 100644 --- a/src/vrend_shader.h +++ b/src/vrend_shader.h @@ -44,13 +44,12 @@ struct vrend_array { struct vrend_shader_info { uint32_t samplers_used_mask; uint32_t images_used_mask; + uint32_t ubo_used_mask; uint32_t ssbo_used_mask; int num_consts; int num_inputs; int num_interps; int num_outputs; - int num_ubos; - int ubo_idx[32]; bool ubo_indirect; uint8_t num_indirect_generic_outputs; uint8_t num_indirect_patch_outputs;