[D3D12] Fix constant-alpha blending in the RTV path
This commit is contained in:
committed by
Radosław Gliński
parent
7cd47947b0
commit
4cc584f47d
@@ -2831,7 +2831,8 @@ bool D3D12CommandProcessor::IssueDraw(xenos::PrimitiveType primitive_type,
|
||||
#endif
|
||||
// Update viewport, scissor, blend factor and stencil reference.
|
||||
UpdateFixedFunctionState(viewport_info, scissor, primitive_polygonal,
|
||||
normalized_depth_control);
|
||||
normalized_depth_control, normalized_color_mask,
|
||||
bound_depth_and_color_render_target_bits);
|
||||
|
||||
// Update system constants before uploading them.
|
||||
// TODO(Triang3l): With ROV, pass the disabled render target mask for safety.
|
||||
@@ -3902,7 +3903,9 @@ void D3D12CommandProcessor::ClearCommandAllocatorCache() {
|
||||
void D3D12CommandProcessor::UpdateFixedFunctionState(
|
||||
const draw_util::ViewportInfo& viewport_info,
|
||||
const draw_util::Scissor& scissor, bool primitive_polygonal,
|
||||
reg::RB_DEPTHCONTROL normalized_depth_control) {
|
||||
reg::RB_DEPTHCONTROL normalized_depth_control,
|
||||
uint32_t normalized_color_mask,
|
||||
uint32_t bound_depth_and_color_render_target_bits) {
|
||||
#if XE_GPU_FINE_GRAINED_DRAW_SCOPES
|
||||
SCOPE_profile_cpu_f("gpu");
|
||||
#endif // XE_GPU_FINE_GRAINED_DRAW_SCOPES
|
||||
@@ -3936,6 +3939,51 @@ void D3D12CommandProcessor::UpdateFixedFunctionState(
|
||||
regs.Get<float>(XE_GPU_REG_RB_BLEND_BLUE),
|
||||
regs.Get<float>(XE_GPU_REG_RB_BLEND_ALPHA),
|
||||
};
|
||||
if (!GetD3D12Provider().IsAlphaBlendFactorSupported()) {
|
||||
bool color_uses_constant_color = false;
|
||||
bool color_uses_constant_alpha = false;
|
||||
for (uint32_t i = 0; i < xenos::kMaxColorRenderTargets; ++i) {
|
||||
// Ignore unbound targets and targets that don't write RGB, since their
|
||||
// color blend factors don't affect the host output merger.
|
||||
if (!(bound_depth_and_color_render_target_bits &
|
||||
(uint32_t(1) << (1 + i))) ||
|
||||
!((normalized_color_mask >> (i * 4)) & 0b0111)) {
|
||||
continue;
|
||||
}
|
||||
auto blend_control = regs.Get<reg::RB_BLENDCONTROL>(
|
||||
reg::RB_BLENDCONTROL::rt_register_indices[i]);
|
||||
// Direct3D 12 ignores blend factors for MIN and MAX.
|
||||
if (blend_control.color_comb_fcn == xenos::BlendOp::kMin ||
|
||||
blend_control.color_comb_fcn == xenos::BlendOp::kMax) {
|
||||
continue;
|
||||
}
|
||||
const xenos::BlendFactor color_blend_factors[] = {
|
||||
blend_control.color_srcblend, blend_control.color_destblend};
|
||||
for (xenos::BlendFactor color_blend_factor : color_blend_factors) {
|
||||
switch (color_blend_factor) {
|
||||
case xenos::BlendFactor::kConstantColor:
|
||||
case xenos::BlendFactor::kOneMinusConstantColor:
|
||||
color_uses_constant_color = true;
|
||||
break;
|
||||
case xenos::BlendFactor::kConstantAlpha:
|
||||
case xenos::BlendFactor::kOneMinusConstantAlpha:
|
||||
color_uses_constant_alpha = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Legacy D3D12 has only a four-component constant-color factor. If the
|
||||
// draw needs only the scalar constant-alpha factor, emulate it by
|
||||
// replicating A. Mixed constant-color and constant-alpha use can't be
|
||||
// represented exactly, so preserve the color factor in that case.
|
||||
if (color_uses_constant_alpha && !color_uses_constant_color) {
|
||||
blend_factor[0] = blend_factor[3];
|
||||
blend_factor[1] = blend_factor[3];
|
||||
blend_factor[2] = blend_factor[3];
|
||||
}
|
||||
}
|
||||
// std::memcmp instead of != so in case of NaN, every draw won't be
|
||||
// invalidating it.
|
||||
ff_blend_factor_update_needed_ |=
|
||||
|
||||
@@ -452,10 +452,12 @@ class D3D12CommandProcessor final : public CommandProcessor {
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE& cpu_handle_out,
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE& gpu_handle_out);
|
||||
|
||||
void UpdateFixedFunctionState(const draw_util::ViewportInfo& viewport_info,
|
||||
const draw_util::Scissor& scissor,
|
||||
bool primitive_polygonal,
|
||||
reg::RB_DEPTHCONTROL normalized_depth_control);
|
||||
void UpdateFixedFunctionState(
|
||||
const draw_util::ViewportInfo& viewport_info,
|
||||
const draw_util::Scissor& scissor, bool primitive_polygonal,
|
||||
reg::RB_DEPTHCONTROL normalized_depth_control,
|
||||
uint32_t normalized_color_mask,
|
||||
uint32_t bound_depth_and_color_render_target_bits);
|
||||
|
||||
template <bool primitive_polygonal, bool edram_rov_used>
|
||||
XE_NOINLINE void UpdateSystemConstantValues_Impl(
|
||||
|
||||
@@ -1544,9 +1544,9 @@ bool PipelineCache::GetCurrentStateDescription(
|
||||
// ONE_MINUS_CONSTANT_COLOR
|
||||
/* 13 */ PipelineBlendFactor::kInvBlendFactor,
|
||||
// CONSTANT_ALPHA
|
||||
/* 14 */ PipelineBlendFactor::kBlendFactor,
|
||||
/* 14 */ PipelineBlendFactor::kAlphaFactor,
|
||||
// ONE_MINUS_CONSTANT_ALPHA
|
||||
/* 15 */ PipelineBlendFactor::kInvBlendFactor,
|
||||
/* 15 */ PipelineBlendFactor::kInvAlphaFactor,
|
||||
/* 16 */ PipelineBlendFactor::kSrcAlphaSat,
|
||||
};
|
||||
// Like kBlendFactorMap, but with color modes changed to alpha. Some
|
||||
@@ -3156,14 +3156,26 @@ ID3D12PipelineState* PipelineCache::CreateD3D12Pipeline(
|
||||
|
||||
// Render targets and blending.
|
||||
state_desc.BlendState.IndependentBlendEnable = true;
|
||||
static constexpr D3D12_BLEND kBlendFactorMap[] = {
|
||||
D3D12_BLEND_ZERO, D3D12_BLEND_ONE,
|
||||
D3D12_BLEND_SRC_COLOR, D3D12_BLEND_INV_SRC_COLOR,
|
||||
D3D12_BLEND_SRC_ALPHA, D3D12_BLEND_INV_SRC_ALPHA,
|
||||
D3D12_BLEND_DEST_COLOR, D3D12_BLEND_INV_DEST_COLOR,
|
||||
D3D12_BLEND_DEST_ALPHA, D3D12_BLEND_INV_DEST_ALPHA,
|
||||
D3D12_BLEND_BLEND_FACTOR, D3D12_BLEND_INV_BLEND_FACTOR,
|
||||
const bool alpha_blend_factor_supported =
|
||||
command_processor_.GetD3D12Provider().IsAlphaBlendFactorSupported();
|
||||
const D3D12_BLEND kBlendFactorMap[] = {
|
||||
D3D12_BLEND_ZERO,
|
||||
D3D12_BLEND_ONE,
|
||||
D3D12_BLEND_SRC_COLOR,
|
||||
D3D12_BLEND_INV_SRC_COLOR,
|
||||
D3D12_BLEND_SRC_ALPHA,
|
||||
D3D12_BLEND_INV_SRC_ALPHA,
|
||||
D3D12_BLEND_DEST_COLOR,
|
||||
D3D12_BLEND_INV_DEST_COLOR,
|
||||
D3D12_BLEND_DEST_ALPHA,
|
||||
D3D12_BLEND_INV_DEST_ALPHA,
|
||||
D3D12_BLEND_BLEND_FACTOR,
|
||||
D3D12_BLEND_INV_BLEND_FACTOR,
|
||||
D3D12_BLEND_SRC_ALPHA_SAT,
|
||||
alpha_blend_factor_supported ? D3D12_BLEND_ALPHA_FACTOR
|
||||
: D3D12_BLEND_BLEND_FACTOR,
|
||||
alpha_blend_factor_supported ? D3D12_BLEND_INV_ALPHA_FACTOR
|
||||
: D3D12_BLEND_INV_BLEND_FACTOR,
|
||||
};
|
||||
// 8 entries for safety since 3 bits from the guest are passed directly.
|
||||
static constexpr D3D12_BLEND_OP kBlendOpMap[] = {
|
||||
|
||||
@@ -180,6 +180,8 @@ class PipelineCache {
|
||||
kBlendFactor,
|
||||
kInvBlendFactor,
|
||||
kSrcAlphaSat,
|
||||
kAlphaFactor,
|
||||
kInvAlphaFactor,
|
||||
};
|
||||
|
||||
// Update PipelineDescription::kVersion if anything is changed!
|
||||
@@ -237,7 +239,7 @@ class PipelineCache {
|
||||
PipelineRenderTarget render_targets[xenos::kMaxColorRenderTargets];
|
||||
|
||||
inline bool operator==(const PipelineDescription& other) const;
|
||||
static constexpr uint32_t kVersion = 0x20260716;
|
||||
static constexpr uint32_t kVersion = 0x20260815;
|
||||
});
|
||||
|
||||
XEPACKEDSTRUCT(PipelineStoredDescription, {
|
||||
|
||||
@@ -463,6 +463,12 @@ bool D3D12Provider::Initialize() {
|
||||
unaligned_block_textures_supported_ =
|
||||
bool(options8.UnalignedBlockTexturesSupported);
|
||||
}
|
||||
alpha_blend_factor_supported_ = false;
|
||||
D3D12_FEATURE_DATA_D3D12_OPTIONS13 options13 = {};
|
||||
if (SUCCEEDED(device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS13,
|
||||
&options13, sizeof(options13)))) {
|
||||
alpha_blend_factor_supported_ = bool(options13.AlphaBlendFactorSupported);
|
||||
}
|
||||
virtual_address_bits_per_resource_ = 0;
|
||||
D3D12_FEATURE_DATA_GPU_VIRTUAL_ADDRESS_SUPPORT virtual_address_support;
|
||||
if (SUCCEEDED(device->CheckFeatureSupport(
|
||||
@@ -478,6 +484,7 @@ bool D3D12Provider::Initialize() {
|
||||
"* Pixel-shader-specified stencil reference: {}\n"
|
||||
"* Programmable sample positions: tier {}\n"
|
||||
"* Rasterizer-ordered views: {}\n"
|
||||
"* Scalar alpha blend factor: {}\n"
|
||||
"* Resource binding: tier {}\n"
|
||||
"* Tiled resources: tier {}\n"
|
||||
"* Unaligned block-compressed textures: {}",
|
||||
@@ -487,6 +494,7 @@ bool D3D12Provider::Initialize() {
|
||||
ps_specified_stencil_reference_supported_ ? "yes" : "no",
|
||||
uint32_t(programmable_sample_positions_tier_),
|
||||
rasterizer_ordered_views_supported_ ? "yes" : "no",
|
||||
alpha_blend_factor_supported_ ? "yes" : "no",
|
||||
uint32_t(resource_binding_tier_), uint32_t(tiled_resources_tier_),
|
||||
unaligned_block_textures_supported_ ? "yes" : "no");
|
||||
|
||||
|
||||
@@ -114,6 +114,9 @@ class D3D12Provider : public GraphicsProvider {
|
||||
bool AreRasterizerOrderedViewsSupported() const {
|
||||
return rasterizer_ordered_views_supported_;
|
||||
}
|
||||
bool IsAlphaBlendFactorSupported() const {
|
||||
return alpha_blend_factor_supported_;
|
||||
}
|
||||
D3D12_RESOURCE_BINDING_TIER GetResourceBindingTier() const {
|
||||
return resource_binding_tier_;
|
||||
}
|
||||
@@ -210,6 +213,7 @@ class D3D12Provider : public GraphicsProvider {
|
||||
uint32_t virtual_address_bits_per_resource_;
|
||||
bool ps_specified_stencil_reference_supported_;
|
||||
bool rasterizer_ordered_views_supported_;
|
||||
bool alpha_blend_factor_supported_;
|
||||
bool unaligned_block_textures_supported_;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user