diff options
author | Gert Wollny <gert.wollny@collabora.com> | 2023-06-03 07:05:25 +0200 |
---|---|---|
committer | Marge Bot <emma+marge@anholt.net> | 2023-06-08 07:53:24 +0000 |
commit | dff7ec2e226a73a4f157b385b468b702324cfdef (patch) | |
tree | 1c6a39b1acca4e722a666a444e2e37586c15ce8c /src | |
parent | 1c102fe30f11d2382d0836264822bdd093b494e5 (diff) |
shader: rework SSBO binding handling
Since the guest sends per-shader SSBOs bindings that are not
necessarily the same accross all stages, even though the client
program binds SSBOs per program, we have to make sure that the
binding points in all shader stages don't overlap, otherwise we
may overwrite SSBOs bindings when a shader program uses SSBOs in
more than just one stage.
With that we don't prefer anymore that the guest sends SSBO binding
offsets, so update the feature check version to signal this change to
the guest. We still handle this case in order to avoid regressions.
v2: Use sized integer and initialize "first" with a known define (Corentin)
Related: https://gitlab.freedesktop.org/mesa/mesa/-/issues/8339
Signed-off-by: Gert Wollny <gert.wollny@collabora.co.uk>
Part-of: <https://gitlab.freedesktop.org/virgl/virglrenderer/-/merge_requests/1139>
Diffstat (limited to 'src')
-rw-r--r-- | src/vrend_renderer.c | 5 | ||||
-rw-r--r-- | src/vrend_shader.c | 29 | ||||
-rw-r--r-- | src/vrend_shader.h | 2 |
3 files changed, 24 insertions, 12 deletions
diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c index c01bdcc..31bb7f6 100644 --- a/src/vrend_renderer.c +++ b/src/vrend_renderer.c @@ -3932,6 +3932,7 @@ static inline void vrend_sync_shader_io(struct vrend_sub_context *sub_ctx, memcpy(key->force_invariant_inputs, prev->sinfo.invariant_outputs, 4 * sizeof(uint32_t)); } + key->ssbo_binding_offset = prev->sinfo.ssbo_last_binding + 1; key->num_in_clip = sub_ctx->shaders[prev_type]->current->var_sinfo.num_out_clip; key->num_in_cull = sub_ctx->shaders[prev_type]->current->var_sinfo.num_out_cull; @@ -5131,7 +5132,7 @@ static void vrend_draw_bind_ssbo_shader(struct vrend_sub_context *sub_ctx, uint32_t offset = sub_ctx->shaders[shader_type]->sinfo.ssbo_binding_offset; mask = sub_ctx->ssbo_used_mask[shader_type] & - (sub_ctx->prog->ssbo_used_mask[shader_type] >> offset); + sub_ctx->prog->ssbo_used_mask[shader_type]; while (mask) { int i = u_bit_scan(&mask); @@ -11757,7 +11758,7 @@ static void vrend_renderer_fill_caps_v2(int gl_ver, int gles_ver, union virgl_c * this value to avoid regressions when a guest with a new mesa version is * run on an old virgl host. Use it also to indicate non-cap fixes on the * host that help enable features in the guest. */ - caps->v2.host_feature_check_version = 16; + caps->v2.host_feature_check_version = 17; /* Forward host GL_RENDERER to the guest. */ strncpy(caps->v2.renderer, renderer, sizeof(caps->v2.renderer) - 1); diff --git a/src/vrend_shader.c b/src/vrend_shader.c index d18bfe2..9ff48ee 100644 --- a/src/vrend_shader.c +++ b/src/vrend_shader.c @@ -231,13 +231,14 @@ struct dump_ctx { struct vrend_shader_sampler samplers[32]; uint32_t samplers_used; + uint32_t ssbo_first_binding; uint32_t ssbo_used_mask; - uint32_t ssbo_binding_offset; uint32_t ssbo_atomic_mask; uint32_t ssbo_array_base; uint32_t ssbo_atomic_array_base; uint32_t ssbo_integer_mask; uint8_t ssbo_memory_qualifier[32]; + int32_t ssbo_last_binding; struct vrend_shader_image images[32]; uint32_t images_used_mask; @@ -1164,7 +1165,9 @@ iter_decls(struct tgsi_iterate_context *iter, ctx->fog_output_mask |= (1 << decl->Semantic.Index); } break; - + case TGSI_FILE_BUFFER: + if (ctx->ssbo_first_binding > decl->Range.First) + ctx->ssbo_first_binding = decl->Range.First; default: break; } @@ -1893,13 +1896,11 @@ iter_declaration(struct tgsi_iterate_context *iter, return false; break; case TGSI_FILE_BUFFER: - if (decl->Range.First >= VREND_MAX_COMBINED_SSBO_BINDING_POINTS) { + if (decl->Range.First + ctx->key->ssbo_binding_offset >= VREND_MAX_COMBINED_SSBO_BINDING_POINTS) { vrend_printf( "Buffer view exceeded, max is %d\n", VREND_MAX_COMBINED_SSBO_BINDING_POINTS); return false; } ctx->ssbo_used_mask |= (1 << decl->Range.First); - if (ctx->ssbo_binding_offset > decl->Range.First) - ctx->ssbo_binding_offset = decl->Range.First; if (decl->Declaration.Atomic) { if (decl->Range.First < ctx->ssbo_atomic_array_base) @@ -1909,6 +1910,8 @@ iter_declaration(struct tgsi_iterate_context *iter, if (decl->Range.First < ctx->ssbo_array_base) ctx->ssbo_array_base = decl->Range.First; } + if (ctx->ssbo_last_binding < decl->Range.Last) + ctx->ssbo_last_binding = decl->Range.Last; break; case TGSI_FILE_CONSTANT: if (decl->Declaration.Dimension && decl->Dim.Index2D != 0) { @@ -6600,16 +6603,18 @@ static int emit_ios_common(const struct dump_ctx *ctx, while (mask) { int start, count; u_bit_scan_consecutive_range(&mask, &start, &count); + int binding = start + ctx->key->ssbo_binding_offset - ctx->ssbo_first_binding; const char *atomic = (ctx->ssbo_atomic_mask & (1 << start)) ? "atomic" : ""; - emit_hdrf(glsl_strbufs, "layout (binding = %d, std430) buffer %sssbo%d { uint %sssbocontents%d[]; } %sssboarr%s[%d];\n", start, sname, start, sname, start, sname, atomic, count); + emit_hdrf(glsl_strbufs, "layout (binding = %d, std430) buffer %sssbo%d { uint %sssbocontents%d[]; } %sssboarr%s[%d];\n", binding, sname, start, sname, start, sname, atomic, count); } } else { uint32_t mask = ctx->ssbo_used_mask; while (mask) { uint32_t id = u_bit_scan(&mask); + int binding = id + ctx->key->ssbo_binding_offset - ctx->ssbo_first_binding; enum vrend_type_qualifier type = (ctx->ssbo_integer_mask & (1 << id)) ? INT : UINT; char *coherent = ctx->ssbo_memory_qualifier[id] == TGSI_MEMORY_COHERENT ? "coherent" : ""; - emit_hdrf(glsl_strbufs, "layout (binding = %d, std430) %s buffer %sssbo%d { %s %sssbocontents%d[]; };\n", id, coherent, sname, id, + emit_hdrf(glsl_strbufs, "layout (binding = %d, std430) %s buffer %sssbo%d { %s %sssbocontents%d[]; };\n", binding, coherent, sname, id, get_string(type), sname, id); } } @@ -7664,9 +7669,11 @@ static void fill_sinfo(const struct dump_ctx *ctx, struct vrend_shader_info *sin sinfo->fog_input_mask = ctx->fog_input_mask; sinfo->fog_output_mask = ctx->fog_output_mask; - sinfo->ssbo_used_mask = ctx->ssbo_used_mask; - sinfo->ssbo_binding_offset = ctx->ssbo_binding_offset != 0xffffffff ? ctx->ssbo_binding_offset : 0; + sinfo->ssbo_used_mask = ctx->ssbo_used_mask >> ctx->ssbo_first_binding; + sinfo->ssbo_binding_offset = ctx->key->ssbo_binding_offset; + sinfo->ssbo_last_binding = ctx->key->ssbo_binding_offset + ctx->ssbo_last_binding - + (ctx->ssbo_first_binding != UINT32_MAX ? ctx->ssbo_first_binding : 0); sinfo->ubo_indirect = !!(ctx->info.dimension_indirect_files & (1 << TGSI_FILE_CONSTANT)); @@ -7914,6 +7921,7 @@ bool vrend_convert_shader(const struct vrend_context *rctx, /* First pass to deal with edge cases. */ ctx.iter.iterate_declaration = iter_decls; ctx.iter.iterate_instruction = analyze_instruction; + ctx.ssbo_first_binding = UINT32_MAX; bret = tgsi_iterate_shader(tokens, &ctx.iter); if (bret == false) return false; @@ -7933,13 +7941,14 @@ bool vrend_convert_shader(const struct vrend_context *rctx, ctx.key = key; ctx.cfg = cfg; ctx.prog_type = -1; - ctx.ssbo_binding_offset = 0xffffffff; ctx.num_image_arrays = 0; ctx.image_arrays = NULL; ctx.num_sampler_arrays = 0; ctx.sampler_arrays = NULL; ctx.ssbo_array_base = 0xffffffff; ctx.ssbo_atomic_array_base = 0xffffffff; + ctx.ssbo_last_binding = -1; + ctx.image_last_binding = -1; ctx.has_sample_input = false; ctx.req_local_mem = req_local_mem; ctx.guest_sent_io_arrays = false; diff --git a/src/vrend_shader.h b/src/vrend_shader.h index 193a77f..6bea2c6 100644 --- a/src/vrend_shader.h +++ b/src/vrend_shader.h @@ -138,6 +138,7 @@ struct vrend_shader_info { uint32_t ubo_used_mask; uint32_t ssbo_used_mask; uint32_t ssbo_binding_offset; + int32_t ssbo_last_binding; uint32_t shadow_samp_mask; uint32_t attrib_input_mask; uint32_t fs_blend_equation_advanced; @@ -218,6 +219,7 @@ struct vrend_shader_key { uint64_t sampler_views_emulated_rect_mask[VREND_SHADER_SAMPLER_VIEWS_MASK_LENGTH]; uint16_t tex_swizzle[PIPE_MAX_SHADER_SAMPLER_VIEWS]; + uint8_t ssbo_binding_offset; uint8_t alpha_test; uint8_t num_in_cull : 4; uint8_t num_in_clip : 4; |