Skip to content

Commit

Permalink
Fix textureGather (#3922)
Browse files Browse the repository at this point in the history
The code wasn't correctly discarding edge cases for negative texture
coordinates.  For example -2.5 sits in the center of a texel and
for textureGather could go either left or right. We need to avoid that
case.

Also, textureGather always does `nearest` filtering mipmapFilter.
This was fine as it was since it would always pass 0 for mipLevel
which meant the 2nd mip level always provided zero contribution
but arguably it should take the `nearest` path.
  • Loading branch information
greggman authored Aug 28, 2024
1 parent a72996c commit d61b6f2
Showing 1 changed file with 14 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1011,7 +1011,8 @@ export function softwareTextureReadLevel<T extends Dimensionality>(
return softwareTextureReadMipLevel<T>(call, texture, sampler, mipLevel);
}

switch (sampler.mipmapFilter) {
const effectiveMipmapFilter = isBuiltinGather(call.builtin) ? 'nearest' : sampler.mipmapFilter;
switch (effectiveMipmapFilter) {
case 'linear': {
const clampedMipLevel = clamp(mipLevel, { min: 0, max: maxLevel });
const baseMipLevel = Math.floor(clampedMipLevel);
Expand Down Expand Up @@ -1388,6 +1389,16 @@ export async function checkCallResults<T extends Dimensionality>(
` : as texel coord mip level[${mipLevel}]: (${t[0]}, ${t[1]}), face: ${faceNdx}(${kFaceNames[faceNdx]})`
);
}
} else {
for (let mipLevel = 0; mipLevel < (texture.descriptor.mipLevelCount ?? 1); ++mipLevel) {
const mipSize = virtualMipSize(
texture.descriptor.dimension ?? '2d',
texture.descriptor.size,
mipLevel
);
const t = call.coords!.map((v, i) => (v * mipSize[i]).toFixed(3));
errs.push(` : as texel coord @ mip level[${mipLevel}]: (${t.join(', ')})`);
}
}
errs.push(`\
got: ${fix5v(rgbaToArray(gotRGBA))}
Expand Down Expand Up @@ -2558,7 +2569,7 @@ function generateTextureBuiltinInputsImpl<T extends Dimensionality>(
const v1 = Math.floor(v * q[i]);
// If it's nearest or textureGather and we're on the edge of a texel then move us off the edge
// since the edge could choose one texel or another.
const isEdgeCase = v1 % kSubdivisionsPerTexel === edgeRemainder;
const isEdgeCase = Math.abs(v1 % kSubdivisionsPerTexel) === edgeRemainder;
const v2 = isEdgeCase && avoidEdgeCase ? v1 + 1 : v1;
// Convert back to texture coords
return v2 / q[i];
Expand Down Expand Up @@ -3004,7 +3015,7 @@ export function generateSamplePointsCube(
const v1 = Math.floor(v * q[i]);
// If it's nearest or textureGather and we're on the edge of a texel then move us off the edge
// since the edge could choose one texel or another.
const isEdgeCase = v1 % kSubdivisionsPerTexel === edgeRemainder;
const isEdgeCase = Math.abs(v1 % kSubdivisionsPerTexel) === edgeRemainder;
const v2 = isEdgeCase && avoidEdgeCase ? v1 + 1 : v1;
// Convert back to texture coords slightly off
return (v2 + 1 / 16) / q[i];
Expand Down

0 comments on commit d61b6f2

Please sign in to comment.