Shader packs: honor per-colortex blend overrides after output remapping

Fixes #6675.

Retain upstream behavior outside this isolated host/compiler fix.

Co-Authored-By: Codex GPT-6 <[email protected]>
This commit is contained in:
gigamans442andCodex GPT-6 committed 2026-11-01 20:23:51 -05:00
1 parent 0454e97e32
commit e8cbb4c13c
2 files changed
+61 -5

No files matched your search

@@ -1341,11 +1341,16 @@ fn build_pass(
} else if let Some(&buffer) = p.buffers.get(l) {
let format = formats[buffer as usize];
let mut state = target(format);
if let (Some(t), Some(b)) = (&mut state, p.blend)
&& format
.guaranteed_format_features(features)
.flags
.contains(wgpu::TextureFormatFeatureFlags::BLENDABLE)
if let (Some(t), Some(b)) = (
&mut state,
p.buffer_blends
.iter()
.find(|(n, _)| *n == buffer)
.map_or(p.blend, |(_, b)| *b),
) && format
.guaranteed_format_features(features)
.flags
.contains(wgpu::TextureFormatFeatureFlags::BLENDABLE)
{
t.blend = Some(blend_state(b));
}
+51
View File
@@ -210,6 +210,8 @@ pub struct PostProgram {
pub flips: Vec<(u32, bool)>,
/// How a gbuffers program's output blends into its buffers; `None` writes them.
pub blend: Option<Blend>,
/// Per-buffer blend overrides, keyed by colortex index (not output location).
pub buffer_blends: Vec<(u32, Option<Blend>)>,
/// Bit n: `colortex<n>MipmapEnabled` in its fragment stage, so buffer n's mip chain is
/// regenerated right before it (6.1.7; not for gbuffers programs).
pub mipmaps: u16,
@@ -860,6 +862,7 @@ impl Loader<'_> {
}
let compute = self.compute(&name);
return (!compute.is_empty()).then(|| PostProgram {
buffer_blends: buffer_blends(self.properties, &name),
flips: flips(self.properties, &name),
name,
group,
@@ -945,6 +948,7 @@ impl Loader<'_> {
_ => Vec::new(),
};
Some(PostProgram {
buffer_blends: buffer_blends(self.properties, &name),
flips: flips(self.properties, &name),
name,
group,
@@ -1043,6 +1047,7 @@ impl Loader<'_> {
.unwrap_or(buffers.len());
buffers.truncate(kept);
Some(PostProgram {
buffer_blends: buffer_blends(self.properties, &name),
flips: flips(self.properties, &name),
name,
group,
@@ -1167,6 +1172,23 @@ fn blend(properties: &Properties, program: &str) -> Option<Option<Blend>> {
Some(Some(factors.try_into().ok()?))
}
/// Blend overrides apply to buffer names even when DRAWBUFFERS remaps locations.
fn buffer_blends(properties: &Properties, program: &str) -> Vec<(u32, Option<Blend>)> {
let prefix = format!("blend.{program}.");
properties
.entries
.iter()
.filter_map(|e| {
let buffer = config::buffer_index(e.key.strip_prefix(&prefix)?)?;
let value = blend(
properties,
&format!("{program}.{}", e.key.strip_prefix(&prefix)?),
)?;
Some((buffer as u32, value))
})
.collect()
}
/// `flip.<program>.<buffer>=<bool>` keys of one program.
fn flips(properties: &Properties, program: &str) -> Vec<(u32, bool)> {
let prefix = format!("flip.{program}.");
@@ -1641,3 +1663,32 @@ mod tests {
);
}
}
#[cfg(test)]
mod buffer_blend_tests {
use super::*;
#[test]
fn buffer_blends_use_colortex_numbers_and_preserve_explicit_off() {
let props = Properties::parse(
"blend.gbuffers_water=off\nblend.gbuffers_water.colortex13=ONE ONE_MINUS_SRC_ALPHA ONE ONE_MINUS_SRC_ALPHA\nblend.gbuffers_water.colortex2=off\n",
&Macros::standard(),
);
let overrides = buffer_blends(&props, "gbuffers_water");
assert_eq!(blend(&props, "gbuffers_water"), Some(None));
assert_eq!(
overrides,
vec![
(
13,
Some([
Factor::One,
Factor::OneMinusSrcAlpha,
Factor::One,
Factor::OneMinusSrcAlpha
])
),
(2, None)
]
);
}
}