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;