Merge pull request #1914 from TheAggie/feat/agc-force-dst-alpha-one

feat(agc): blend against an opaque destination for CB_COLOR_ATTRIB FORCE_DST_ALPHA_1
This commit is contained in:
Dean 2026-10-10 17:42:27 +13:00 committed by GitHub
commit eb283f5c8f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 44 additions and 1 deletions

View File

@ -318,6 +318,23 @@ VkBlendFactor blendFactor(std::uint32_t value) {
}
}
VkBlendFactor colorFactorWithOpaqueDestination(VkBlendFactor factor) {
switch (factor) {
case VK_BLEND_FACTOR_DST_ALPHA: return VK_BLEND_FACTOR_ONE;
case VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA: return VK_BLEND_FACTOR_ZERO;
case VK_BLEND_FACTOR_SRC_ALPHA_SATURATE: return VK_BLEND_FACTOR_ZERO;
default: return factor;
}
}
VkBlendFactor alphaFactorWithOpaqueDestination(VkBlendFactor factor) {
switch (factor) {
case VK_BLEND_FACTOR_DST_ALPHA: case VK_BLEND_FACTOR_DST_COLOR: return VK_BLEND_FACTOR_ONE;
case VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA: case VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR: return VK_BLEND_FACTOR_ZERO;
default: return factor;
}
}
VkBlendOp blendOp(std::uint32_t value) {
switch (value) {
case 0: return VK_BLEND_OP_ADD;
@ -684,6 +701,12 @@ State DecodeState(const QueueState& queue) {
state.dstColorBlendFactor = state.dstAlphaBlendFactor;
state.colorBlendOp = state.alphaBlendOp;
}
if ((read(cx, 0x31d + slot * 0xfu) & 0x20000u) != 0) {
state.srcColorBlendFactor = colorFactorWithOpaqueDestination(state.srcColorBlendFactor);
state.dstColorBlendFactor = colorFactorWithOpaqueDestination(state.dstColorBlendFactor);
state.srcAlphaBlendFactor = alphaFactorWithOpaqueDestination(state.srcAlphaBlendFactor);
state.dstAlphaBlendFactor = alphaFactorWithOpaqueDestination(state.dstAlphaBlendFactor);
}
for (std::uint32_t i = 0; i < 4; ++i) result.blendConstants[i] = readFloat(cx, 0x105 + i);
}
result.blends[color.exportIndex] = state;
@ -738,7 +761,7 @@ ColorTarget DecodeColorBuffer(const Registers& cx, std::uint32_t slot) {
const auto slice = view & 0x1fffu;
Require(slice == ((view >> 13u) & 0x1fffu), "color views of several array slices are unsupported");
const auto viewMip = (view >> 26u) & 0xfu;
zero(cx, 0x31d + stride, ~0u, "color samples, fragments or destination alpha override");
zero(cx, 0x31d + stride, ~0x20000u, "color samples, fragments or destination alpha override");
const auto attrib2 = read(cx, 0x3b0 + slot);
const auto maxMip = attrib2 >> 28u;
Require(viewMip <= maxMip, "color view mip exceeds the surface");

View File

@ -572,6 +572,25 @@ void PixelInputLayoutTests() {
Require(!readsBuiltin(read, spv::BuiltInFragCoord) && !readsBuiltin(read, spv::BuiltInBaryCoordKHR), "an ADDR-only centroid pair was loaded");
}
void OpaqueDestinationAlphaTests() {
auto queue = makeState();
for (std::uint32_t constant = 0x105; constant < 0x109; ++constant) queue.context[constant] = 0;
queue.context[0x1e0] = (1u << 30u) | (1u << 29u) | 6u | (7u << 8u) | (8u << 16u) | (10u << 24u);
auto blend = AgcDriver::Graphics::DecodeState(queue).blend;
Require(blend.srcColorBlendFactor == VK_BLEND_FACTOR_DST_ALPHA && blend.dstColorBlendFactor == VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA, "color blend factors changed");
Require(blend.srcAlphaBlendFactor == VK_BLEND_FACTOR_DST_COLOR && blend.dstAlphaBlendFactor == VK_BLEND_FACTOR_SRC_ALPHA_SATURATE, "alpha blend factors changed");
queue.context[0x31d] = 0x20000u;
blend = AgcDriver::Graphics::DecodeState(queue).blend;
Require(blend.srcColorBlendFactor == VK_BLEND_FACTOR_ONE && blend.dstColorBlendFactor == VK_BLEND_FACTOR_ZERO, "an opaque destination left a destination-alpha color factor");
Require(blend.srcAlphaBlendFactor == VK_BLEND_FACTOR_ONE && blend.dstAlphaBlendFactor == VK_BLEND_FACTOR_SRC_ALPHA_SATURATE, "an opaque destination left a destination alpha factor");
queue.context[0x1e0] = (1u << 30u) | 10u | (9u << 8u);
blend = AgcDriver::Graphics::DecodeState(queue).blend;
Require(blend.srcColorBlendFactor == VK_BLEND_FACTOR_ZERO && blend.dstColorBlendFactor == VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR, "alpha saturation with an opaque destination");
Require(blend.dstAlphaBlendFactor == VK_BLEND_FACTOR_ZERO, "an opaque destination left a destination-color alpha factor");
queue.context[0x31d] = 0x40000u;
expectFailure([&] { AgcDriver::Graphics::DecodeState(queue); }, "destination alpha override");
}
void DisabledColorTests() {
auto queue = makeState();
queue.context[0x8e] = 0;
@ -2982,6 +3001,7 @@ int main() {
orderedPixelShaderTests();
ConservativeRasterizationTests();
DisabledColorTests();
OpaqueDestinationAlphaTests();
CompactedExportTests();
ReversedComponentOrderTests();
metadataPassTests();