From fe82483966f1d578bbcb177a662ee1ceb30c8666 Mon Sep 17 00:00:00 2001 From: Gert Wollny Date: Tue, 19 Oct 2021 11:37:31 +0200 Subject: [PATCH] vrend/shader: Set all FS output locations if possible Sometimes we receive FS shaders where some output was optimized away. In this case we have to set the output locations explicitly, but it is no problem if we always do this. On GL this can always be done by using glBindFragDataLocationIndexed, it is supported since at least GL 3.3, and the alternative, setting the layouts in the shader, requires the same OpenGL. On GLES we have to emit explict locations if EXT_blend_func_extended is not supported. This fises rendering of "The Long Dark". v2: - Emit EXT_blend_func_extended in FS if extension is available since this is required when not emitting the explicit locations (Robert Wenzel) - call glBindFragDataLocationIndexedEXT on GLES because that's what the extension requires v3: use sizoef(buf) instead of hard-coding size (John) Related: #223 Signed-off-by: Gert Wollny Reviewed-by: maksym.wezdecki@collabora.com (v2) Reviewed-by: John Bates --- src/virgl_hw.h | 3 ++- src/vrend_renderer.c | 32 +++++++++++++++++++++++--------- src/vrend_shader.c | 9 +++++++++ src/vrend_shader.h | 3 +++ 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/virgl_hw.h b/src/virgl_hw.h index 81cef9c..f9bf780 100644 --- a/src/virgl_hw.h +++ b/src/virgl_hw.h @@ -625,7 +625,8 @@ enum virgl_ctx_errors { VIRGL_ERROR_CTX_ILLEGAL_FORMAT, VIRGL_ERROR_CTX_ILLEGAL_SAMPLER_VIEW_TARGET, VIRGL_ERROR_CTX_TRANSFER_IOV_BOUNDS, - VIRGL_ERROR_CTX_ILLEGAL_DUAL_SRC_BLEND + VIRGL_ERROR_CTX_ILLEGAL_DUAL_SRC_BLEND, + VIRGL_ERROR_CTX_UNSUPPORTED_FUNCTION, }; /** diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c index ebafbb1..21790e9 100644 --- a/src/vrend_renderer.c +++ b/src/vrend_renderer.c @@ -971,6 +971,8 @@ static const char *vrend_ctx_error_strings[] = { [VIRGL_ERROR_CTX_ILLEGAL_FORMAT] = "Illegal format ID", [VIRGL_ERROR_CTX_ILLEGAL_SAMPLER_VIEW_TARGET] = "Illegat target for sampler view", [VIRGL_ERROR_CTX_TRANSFER_IOV_BOUNDS] = "IOV data size exceeds resource capacity", + [VIRGL_ERROR_CTX_ILLEGAL_DUAL_SRC_BLEND]= "Dual source blend not supported", + [VIRGL_ERROR_CTX_UNSUPPORTED_FUNCTION] = "Unsupported host function called", }; void vrend_report_context_error_internal(const char *fname, struct vrend_context *ctx, @@ -1650,20 +1652,32 @@ static struct vrend_linked_shader_program *add_shader_program(struct vrend_sub_c glAttachShader(prog_id, fs->id); if (fs->sel->sinfo.num_outputs > 1) { - if (util_blend_state_is_dual(&sub_ctx->blend_state, 0)) { + sprog->dual_src_linked = util_blend_state_is_dual(&sub_ctx->blend_state, 0); + if (sprog->dual_src_linked) { if (has_feature(feat_dual_src_blend)) { - glBindFragDataLocationIndexed(prog_id, 0, 0, "fsout_c0"); - glBindFragDataLocationIndexed(prog_id, 0, 1, "fsout_c1"); + if (!vrend_state.use_gles) { + glBindFragDataLocationIndexed(prog_id, 0, 0, "fsout_c0"); + glBindFragDataLocationIndexed(prog_id, 0, 1, "fsout_c1"); + } else { + glBindFragDataLocationIndexedEXT(prog_id, 0, 0, "fsout_c0"); + glBindFragDataLocationIndexedEXT(prog_id, 0, 1, "fsout_c1"); + } } else { vrend_report_context_error(sub_ctx->parent, VIRGL_ERROR_CTX_ILLEGAL_DUAL_SRC_BLEND, 0); } - sprog->dual_src_linked = true; - } else { - if (has_feature(feat_dual_src_blend)) { - glBindFragDataLocationIndexed(prog_id, 0, 0, "fsout_c0"); - glBindFragDataLocationIndexed(prog_id, 1, 0, "fsout_c1"); + } else if (has_feature(feat_dual_src_blend)) { + for (int i = 0; i < fs->sel->sinfo.num_outputs; ++i) { + if (fs->sel->sinfo.fs_output_layout[i] >= 0) { + char buf[64]; + snprintf(buf, sizeof(buf), "fsout_c%d", fs->sel->sinfo.fs_output_layout[i]); + if (!vrend_state.use_gles) + glBindFragDataLocationIndexed(prog_id, fs->sel->sinfo.fs_output_layout[i], 0, buf); + else + glBindFragDataLocationIndexedEXT(prog_id, fs->sel->sinfo.fs_output_layout[i], 0, buf); + } } - sprog->dual_src_linked = false; + } else { + vrend_report_context_error(sub_ctx->parent, VIRGL_ERROR_CTX_UNSUPPORTED_FUNCTION, 0); } } else sprog->dual_src_linked = false; diff --git a/src/vrend_shader.c b/src/vrend_shader.c index dc33cc4..21d78d7 100644 --- a/src/vrend_shader.c +++ b/src/vrend_shader.c @@ -5653,6 +5653,8 @@ static void emit_header(const struct dump_ctx *ctx, struct vrend_glsl_strbufs *g emit_ext(glsl_strbufs, "EXT_shader_framebuffer_fetch", "require"); if (ctx->shader_req_bits & SHADER_REQ_BLEND_EQUATION_ADVANCED) emit_ext(glsl_strbufs, "KHR_blend_equation_advanced", "require"); + if (ctx->cfg->has_dual_src_blend) + emit_ext(glsl_strbufs, "EXT_blend_func_extended", "require"); } if (ctx->shader_req_bits & SHADER_REQ_VIEWPORT_IDX) @@ -7176,6 +7178,13 @@ static void fill_sinfo(const struct dump_ctx *ctx, struct vrend_shader_info *sin sinfo->generic_outputs_layout[sinfo->out.num_generic_and_patch].usage_mask = ctx->outputs[i].usage_mask; sinfo->out.num_generic_and_patch++; } + + if (ctx->prog_type == TGSI_PROCESSOR_FRAGMENT) { + if (ctx->outputs[i].name == TGSI_SEMANTIC_COLOR) + sinfo->fs_output_layout[i] = ctx->outputs[i].sid; + else + sinfo->fs_output_layout[i] = -1; + } } sinfo->so_names = ctx->so_names; diff --git a/src/vrend_shader.h b/src/vrend_shader.h index 8eda323..98a051c 100644 --- a/src/vrend_shader.h +++ b/src/vrend_shader.h @@ -106,6 +106,9 @@ struct vrend_shader_info { char **so_names; struct pipe_stream_output_info so_info; + /* 8 cbufs + depth + stencil + samplemask */ + int8_t fs_output_layout[12]; + uint32_t samplers_used_mask; uint32_t images_used_mask; uint32_t ubo_used_mask;