summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGert Wollny <gert.wollny@collabora.com>2023-06-03 07:05:25 +0200
committerMarge Bot <emma+marge@anholt.net>2023-06-08 07:53:24 +0000
commitdff7ec2e226a73a4f157b385b468b702324cfdef (patch)
tree1c6a39b1acca4e722a666a444e2e37586c15ce8c /src
parent1c102fe30f11d2382d0836264822bdd093b494e5 (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.c5
-rw-r--r--src/vrend_shader.c29
-rw-r--r--src/vrend_shader.h2
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;