/* these states are affectd by rasterizer_discard */
VkSampleCountFlagBits samples;
bool use_color_attachments;
+ bool use_dual_src_blend;
uint32_t color_attachment_count;
VkFormat color_attachment_formats[MAX_RTS];
VkFormat depth_attachment_format;
}
}
+static bool tu_blend_factor_is_dual_src(VkBlendFactor factor)
+{
+ switch (factor) {
+ case VK_BLEND_FACTOR_SRC1_COLOR:
+ case VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR:
+ case VK_BLEND_FACTOR_SRC1_ALPHA:
+ case VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool
+tu_blend_state_is_dual_src(const VkPipelineColorBlendStateCreateInfo *info)
+{
+ if (!info)
+ return false;
+
+ for (unsigned i = 0; i < info->attachmentCount; i++) {
+ const VkPipelineColorBlendAttachmentState *blend = &info->pAttachments[i];
+ if (tu_blend_factor_is_dual_src(blend->srcColorBlendFactor) ||
+ tu_blend_factor_is_dual_src(blend->dstColorBlendFactor) ||
+ tu_blend_factor_is_dual_src(blend->srcAlphaBlendFactor) ||
+ tu_blend_factor_is_dual_src(blend->dstAlphaBlendFactor))
+ return true;
+ }
+
+ return false;
+}
+
static enum pc_di_primtype
tu6_primtype(VkPrimitiveTopology topology)
{
static void
tu6_emit_fs_outputs(struct tu_cs *cs,
const struct ir3_shader_variant *fs,
- uint32_t mrt_count)
+ uint32_t mrt_count, bool dual_src_blend)
{
uint32_t smask_regid, posz_regid;
tu_cs_emit_pkt4(cs, REG_A6XX_SP_FS_OUTPUT_CNTL0, 2);
tu_cs_emit(cs, A6XX_SP_FS_OUTPUT_CNTL0_DEPTH_REGID(posz_regid) |
A6XX_SP_FS_OUTPUT_CNTL0_SAMPMASK_REGID(smask_regid) |
+ COND(dual_src_blend, A6XX_SP_FS_OUTPUT_CNTL0_DUAL_COLOR_IN_ENABLE) |
0xfc000000);
tu_cs_emit(cs, A6XX_SP_FS_OUTPUT_CNTL1_MRT(mrt_count));
tu_cs_emit_pkt4(cs, REG_A6XX_RB_FS_OUTPUT_CNTL0, 2);
tu_cs_emit(cs, COND(fs->writes_pos, A6XX_RB_FS_OUTPUT_CNTL0_FRAG_WRITES_Z) |
- COND(fs->writes_smask, A6XX_RB_FS_OUTPUT_CNTL0_FRAG_WRITES_SAMPMASK));
+ COND(fs->writes_smask, A6XX_RB_FS_OUTPUT_CNTL0_FRAG_WRITES_SAMPMASK) |
+ COND(dual_src_blend, A6XX_RB_FS_OUTPUT_CNTL0_DUAL_COLOR_IN_ENABLE));
tu_cs_emit(cs, A6XX_RB_FS_OUTPUT_CNTL1_MRT(mrt_count));
tu_cs_emit_regs(cs,
tu6_emit_vpc(cs, vs, gs, fs, binning_pass, tf);
tu6_emit_vpc_varying_modes(cs, fs, binning_pass);
tu6_emit_fs_inputs(cs, fs);
- tu6_emit_fs_outputs(cs, fs, builder->color_attachment_count);
+ tu6_emit_fs_outputs(cs, fs, builder->color_attachment_count,
+ builder->use_dual_src_blend);
tu6_emit_shader_object(cs, MESA_SHADER_VERTEX, vs, binary_bo,
binning_pass ? builder->binning_vs_offset : builder->shader_offsets[MESA_SHADER_VERTEX]);
static void
tu6_emit_blend_control(struct tu_cs *cs,
uint32_t blend_enable_mask,
+ bool dual_src_blend,
const VkPipelineMultisampleStateCreateInfo *msaa_info)
{
assert(!msaa_info->alphaToOneEnable);
uint32_t sp_blend_cntl = A6XX_SP_BLEND_CNTL_UNK8;
if (blend_enable_mask)
sp_blend_cntl |= A6XX_SP_BLEND_CNTL_ENABLED;
+ if (dual_src_blend)
+ sp_blend_cntl |= A6XX_SP_BLEND_CNTL_DUAL_COLOR_IN_ENABLE;
if (msaa_info->alphaToCoverageEnable)
sp_blend_cntl |= A6XX_SP_BLEND_CNTL_ALPHA_TO_COVERAGE;
A6XX_RB_BLEND_CNTL_ENABLE_BLEND(blend_enable_mask) |
A6XX_RB_BLEND_CNTL_INDEPENDENT_BLEND |
A6XX_RB_BLEND_CNTL_SAMPLE_MASK(sample_mask);
+ if (dual_src_blend)
+ rb_blend_cntl |= A6XX_RB_BLEND_CNTL_DUAL_COLOR_IN_ENABLE;
if (msaa_info->alphaToCoverageEnable)
rb_blend_cntl |= A6XX_RB_BLEND_CNTL_ALPHA_TO_COVERAGE;
tu6_emit_sample_locations(&blend_cs, samp_loc);
}
- tu6_emit_blend_control(&blend_cs, blend_enable_mask, msaa_info);
+ tu6_emit_blend_control(&blend_cs, blend_enable_mask,
+ builder->use_dual_src_blend, msaa_info);
pipeline->blend.state_ib = tu_cs_end_sub_stream(&pipeline->cs, &blend_cs);
}
builder->color_attachment_formats[i] = pass->attachments[a].format;
builder->use_color_attachments = true;
}
+
+ if (tu_blend_state_is_dual_src(create_info->pColorBlendState)) {
+ builder->color_attachment_count++;
+ builder->use_dual_src_blend = true;
+ }
}
}