From bf29ebc0a79d61c4f12380ba5f9b107ff77b03c0 Mon Sep 17 00:00:00 2001 From: Gert Wollny Date: Sat, 2 Jul 2022 10:06:27 +0200 Subject: [PATCH] virgl: Submit the TGSI_PROPERTY_SEPARABLE_PROGRAM when the host understands it We can't unconditionally support separable shader objects on the host, so submit the property only if the shader is actually separable, the host knows about the property, and supports SSO. Without support for SSOs, the host can still compile and link the shaders, it needs to do more work on interface matching though. Signed-off-by: Gert Wollny Part-of: --- src/gallium/drivers/virgl/virgl_context.c | 9 +++++++-- src/gallium/drivers/virgl/virgl_context.h | 3 ++- src/gallium/drivers/virgl/virgl_tgsi.c | 13 ++++++++++++- src/virtio/virtio-gpu/virgl_hw.h | 1 + 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/gallium/drivers/virgl/virgl_context.c b/src/gallium/drivers/virgl/virgl_context.c index b78ca18f15b..c90b3ea7ec8 100644 --- a/src/gallium/drivers/virgl/virgl_context.c +++ b/src/gallium/drivers/virgl/virgl_context.c @@ -682,18 +682,23 @@ static void *virgl_shader_encoder(struct pipe_context *ctx, const struct tgsi_token *ntt_tokens = NULL; struct tgsi_token *new_tokens; int ret; + bool is_separable = false; if (shader->type == PIPE_SHADER_IR_NIR) { struct nir_to_tgsi_options options = { .unoptimized_ra = true }; nir_shader *s = nir_shader_clone(NULL, shader->ir.nir); + + /* Propagare the separable shader property to the host, unless + * it is an internal shader - these are marked separable even though they are not. */ + is_separable = s->info.separate_shader && !s->info.internal; ntt_tokens = tokens = nir_to_tgsi_options(s, vctx->base.screen, &options); /* takes ownership */ } else { tokens = shader->tokens; } - new_tokens = virgl_tgsi_transform((struct virgl_screen *)vctx->base.screen, tokens); + new_tokens = virgl_tgsi_transform((struct virgl_screen *)vctx->base.screen, tokens, is_separable); if (!new_tokens) return NULL; @@ -1378,7 +1383,7 @@ static void *virgl_create_compute_state(struct pipe_context *ctx, tokens = state->prog; } - void *new_tokens = virgl_tgsi_transform((struct virgl_screen *)vctx->base.screen, tokens); + void *new_tokens = virgl_tgsi_transform((struct virgl_screen *)vctx->base.screen, tokens, false); if (!new_tokens) return NULL; diff --git a/src/gallium/drivers/virgl/virgl_context.h b/src/gallium/drivers/virgl/virgl_context.h index 924f1a82227..3b6ee900214 100644 --- a/src/gallium/drivers/virgl/virgl_context.h +++ b/src/gallium/drivers/virgl/virgl_context.h @@ -127,7 +127,8 @@ void virgl_init_blit_functions(struct virgl_context *vctx); void virgl_init_query_functions(struct virgl_context *vctx); void virgl_init_so_functions(struct virgl_context *vctx); -struct tgsi_token *virgl_tgsi_transform(struct virgl_screen *vscreen, const struct tgsi_token *tokens_in); +struct tgsi_token *virgl_tgsi_transform(struct virgl_screen *vscreen, const struct tgsi_token *tokens_in, + bool is_separable); bool virgl_can_rebind_resource(struct virgl_context *vctx, diff --git a/src/gallium/drivers/virgl/virgl_tgsi.c b/src/gallium/drivers/virgl/virgl_tgsi.c index a98a74ea2eb..c4bec480512 100644 --- a/src/gallium/drivers/virgl/virgl_tgsi.c +++ b/src/gallium/drivers/virgl/virgl_tgsi.c @@ -59,6 +59,7 @@ struct virgl_transform_context { bool cull_enabled; bool has_precise; bool fake_fp64; + bool is_separable; unsigned next_temp; @@ -186,6 +187,14 @@ virgl_tgsi_transform_prolog(struct tgsi_transform_context * ctx) { struct virgl_transform_context *vtctx = (struct virgl_transform_context *)ctx; + if (vtctx->is_separable) { + struct tgsi_full_property prop = tgsi_default_full_property(); + prop.Property.PropertyName = TGSI_PROPERTY_SEPARABLE_PROGRAM; + prop.Property.NrTokens += 1; + prop.u[0].Data = 1; + ctx->emit_property(ctx, &prop); + } + vtctx->src_temp = vtctx->next_temp; vtctx->next_temp += 4; tgsi_transform_temps_decl(ctx, vtctx->src_temp, vtctx->src_temp + 3); @@ -418,7 +427,8 @@ virgl_tgsi_transform_instruction(struct tgsi_transform_context *ctx, } } -struct tgsi_token *virgl_tgsi_transform(struct virgl_screen *vscreen, const struct tgsi_token *tokens_in) +struct tgsi_token *virgl_tgsi_transform(struct virgl_screen *vscreen, const struct tgsi_token *tokens_in, + bool is_separable) { struct virgl_transform_context transform; const uint newLen = tgsi_num_tokens(tokens_in); @@ -432,6 +442,7 @@ struct tgsi_token *virgl_tgsi_transform(struct virgl_screen *vscreen, const stru transform.has_precise = vscreen->caps.caps.v2.capability_bits & VIRGL_CAP_TGSI_PRECISE; transform.fake_fp64 = vscreen->caps.caps.v2.capability_bits & VIRGL_CAP_FAKE_FP64; + transform.is_separable = is_separable && (vscreen->caps.caps.v2.capability_bits_v2 & VIRGL_CAP_V2_SSO); for (int i = 0; i < ARRAY_SIZE(transform.input_temp); i++) transform.input_temp[i].index = ~0; diff --git a/src/virtio/virtio-gpu/virgl_hw.h b/src/virtio/virtio-gpu/virgl_hw.h index 330ee79b020..eafc0b41912 100644 --- a/src/virtio/virtio-gpu/virgl_hw.h +++ b/src/virtio/virtio-gpu/virgl_hw.h @@ -445,6 +445,7 @@ enum virgl_formats { #define VIRGL_CAP_V2_IMPLICIT_MSAA (1 << 6) #define VIRGL_CAP_V2_COPY_TRANSFER_BOTH_DIRECTIONS (1 << 7) #define VIRGL_CAP_V2_SCANOUT_USES_GBM (1 << 8) +#define VIRGL_CAP_V2_SSO (1 << 9) /* virgl bind flags - these are compatible with mesa 10.5 gallium. * but are fixed, no other should be passed to virgl either. */