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 <gert.wollny@collabora.com>
Reviewed-by: maksym.wezdecki@collabora.com (v2)
Reviewed-by: John Bates <jbates@chromium.org>
macos/master
Gert Wollny 3 years ago
parent 8678763abe
commit fe82483966
  1. 3
      src/virgl_hw.h
  2. 32
      src/vrend_renderer.c
  3. 9
      src/vrend_shader.c
  4. 3
      src/vrend_shader.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,
};
/**

@ -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;

@ -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;

@ -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;

Loading…
Cancel
Save