From 8328265c7309362a3f0430e08f3c1e67c404db4a Mon Sep 17 00:00:00 2001 From: Greggman Date: Fri, 1 Nov 2024 14:51:05 -0700 Subject: [PATCH] Re-enable linear with comparisons. (#4026) It's a little confusing but depth textures used for "sampling" are not filterable but used for "comparisons" they are. | | texture_?d with depth texture | texture_depth_?? | | ----------------------------- | ---------------------------------- | ---------------- | | sampler `'linear'` | bad | bad | | sampler_comparison `'linear'` | N/A | OK | --- src/webgpu/format_info.ts | 16 ++++++- .../call/builtin/textureGather.spec.ts | 10 ++--- .../call/builtin/textureGatherCompare.spec.ts | 42 +++++++++++++++---- .../expression/call/builtin/texture_utils.ts | 9 ++-- 4 files changed, 56 insertions(+), 21 deletions(-) diff --git a/src/webgpu/format_info.ts b/src/webgpu/format_info.ts index 5d3b5becf56e..e65838fd2a10 100644 --- a/src/webgpu/format_info.ts +++ b/src/webgpu/format_info.ts @@ -1793,9 +1793,21 @@ export function canUseAsRenderTarget(format: GPUTextureFormat) { return kTextureFormatInfo[format].colorRender || isDepthOrStencilTextureFormat(format); } -export function isFilterable(format: GPUTextureFormat) { +export function is32Float(format: GPUTextureFormat) { + return format === 'r32float' || format === 'rg32float' || format === 'rgba32float'; +} + +/** + * Returns true if texture is filterable as `texture_xxx` + * + * examples: + * * 'rgba8unorm' -> true + * * 'depth16unorm' -> false + * * 'rgba32float' -> true (you need to enable feature 'float32-filterable') + */ +export function isFilterableAsTextureF32(format: GPUTextureFormat) { const info = kTextureFormatInfo[format]; - return info.color?.type === 'float'; + return info.color?.type === 'float' || is32Float(format); } export const kCompatModeUnsupportedStorageTextureFormats: readonly GPUTextureFormat[] = [ diff --git a/src/webgpu/shader/execution/expression/call/builtin/textureGather.spec.ts b/src/webgpu/shader/execution/expression/call/builtin/textureGather.spec.ts index 4b5d5c65e806..487ac934dbed 100644 --- a/src/webgpu/shader/execution/expression/call/builtin/textureGather.spec.ts +++ b/src/webgpu/shader/execution/expression/call/builtin/textureGather.spec.ts @@ -28,7 +28,7 @@ import { makeTestGroup } from '../../../../../../common/framework/test_group.js' import { isDepthTextureFormat, isEncodableTextureFormat, - isFilterable, + isFilterableAsTextureF32, kDepthStencilFormats, kAllTextureFormats, } from '../../../../../format_info.js'; @@ -88,7 +88,7 @@ Parameters: .combine('format', kAllTextureFormats) .filter(t => isFillable(t.format)) .combine('filt', ['nearest', 'linear'] as const) - .filter(t => t.filt === 'nearest' || isFilterable(t.format)) + .filter(t => t.filt === 'nearest' || isFilterableAsTextureF32(t.format)) .combine('modeU', kShortAddressModes) .combine('modeV', kShortAddressModes) .combine('offset', [false, true] as const) @@ -186,7 +186,7 @@ Parameters: .combine('format', kAllTextureFormats) .filter(t => isFillable(t.format)) .combine('filt', ['nearest', 'linear'] as const) - .filter(t => t.filt === 'nearest' || isFilterable(t.format)) + .filter(t => t.filt === 'nearest' || isFilterableAsTextureF32(t.format)) .combine('mode', kShortAddressModes) .beginSubcases() .combine('C', ['i32', 'u32'] as const) @@ -295,7 +295,7 @@ Parameters: .combine('format', kAllTextureFormats) .filter(t => isFillable(t.format)) .combine('filt', ['nearest', 'linear'] as const) - .filter(t => t.filt === 'nearest' || isFilterable(t.format)) + .filter(t => t.filt === 'nearest' || isFilterableAsTextureF32(t.format)) .combine('modeU', kShortAddressModes) .combine('modeV', kShortAddressModes) .combine('offset', [false, true] as const) @@ -402,7 +402,7 @@ Parameters: .combine('format', kAllTextureFormats) .filter(t => isFillable(t.format)) .combine('filt', ['nearest', 'linear'] as const) - .filter(t => t.filt === 'nearest' || isFilterable(t.format)) + .filter(t => t.filt === 'nearest' || isFilterableAsTextureF32(t.format)) .combine('mode', kShortAddressModes) .beginSubcases() .combine('samplePoints', kCubeSamplePointMethods) diff --git a/src/webgpu/shader/execution/expression/call/builtin/textureGatherCompare.spec.ts b/src/webgpu/shader/execution/expression/call/builtin/textureGatherCompare.spec.ts index 09c186437f0a..f86a152c19bc 100644 --- a/src/webgpu/shader/execution/expression/call/builtin/textureGatherCompare.spec.ts +++ b/src/webgpu/shader/execution/expression/call/builtin/textureGatherCompare.spec.ts @@ -76,6 +76,7 @@ Parameters: .filter(t => isDepthTextureFormat(t.format)) // MAINTENANCE_TODO: Remove when support for depth24plus, depth24plus-stencil8, and depth32float-stencil8 is added. .filter(t => isEncodableTextureFormat(t.format)) + .combine('filt', ['nearest', 'linear'] as const) .combine('modeU', kShortAddressModes) .combine('modeV', kShortAddressModes) .combine('offset', [false, true] as const) @@ -88,7 +89,17 @@ Parameters: t.skipIfTextureFormatNotSupported(t.params.format); }) .fn(async t => { - const { format, stage, samplePoints, A, modeU, modeV, compare, offset } = t.params; + const { + format, + stage, + samplePoints, + A, + modeU, + modeV, + filt: minFilter, + compare, + offset, + } = t.params; const viewDimension = '2d-array'; const size = chooseTextureSize({ minSize: 8, minBlocks: 4, format, viewDimension }); @@ -105,6 +116,9 @@ Parameters: addressModeU: kShortAddressModeToAddressMode[modeU], addressModeV: kShortAddressModeToAddressMode[modeV], compare, + minFilter, + magFilter: minFilter, + mipmapFilter: minFilter, }; const calls: TextureCall[] = generateTextureBuiltinInputs2D(50, { @@ -115,7 +129,7 @@ Parameters: arrayIndex: { num: texture.depthOrArrayLayers, type: A }, depthRef: true, offset, - hashInputs: [stage, format, samplePoints, A, modeU, modeV, offset], + hashInputs: [stage, format, samplePoints, A, modeU, modeV, minFilter, offset], }).map(({ coords, arrayIndex, depthRef, offset }) => { return { builtin: 'textureGatherCompare', @@ -175,6 +189,7 @@ Parameters: .filter(t => isDepthTextureFormat(t.format)) // MAINTENANCE_TODO: Remove when support for depth24plus, depth24plus-stencil8, and depth32float-stencil8 is added. .filter(t => isEncodableTextureFormat(t.format)) + .combine('filt', ['nearest', 'linear'] as const) .combine('mode', kShortAddressModes) .beginSubcases() .combine('samplePoints', kCubeSamplePointMethods) @@ -185,7 +200,7 @@ Parameters: t.skipIfTextureViewDimensionNotSupported('cube-array'); }) .fn(async t => { - const { format, A, stage, samplePoints, mode, compare } = t.params; + const { format, A, stage, samplePoints, mode, filt: minFilter, compare } = t.params; const viewDimension: GPUTextureViewDimension = 'cube-array'; const size = chooseTextureSize({ minSize: 8, minBlocks: 2, format, viewDimension }); @@ -204,6 +219,9 @@ Parameters: addressModeV: kShortAddressModeToAddressMode[mode], addressModeW: kShortAddressModeToAddressMode[mode], compare, + minFilter, + magFilter: minFilter, + mipmapFilter: minFilter, }; const calls: TextureCall[] = generateSamplePointsCube(50, { @@ -213,7 +231,7 @@ Parameters: textureBuiltin: 'textureGatherCompare', arrayIndex: { num: texture.depthOrArrayLayers / 6, type: A }, depthRef: true, - hashInputs: [stage, format, samplePoints, mode], + hashInputs: [stage, format, samplePoints, mode, minFilter], }).map(({ coords, depthRef, arrayIndex }) => { return { builtin: 'textureGatherCompare', @@ -278,6 +296,7 @@ Parameters: .filter(t => isDepthTextureFormat(t.format)) // MAINTENANCE_TODO: Remove when support for depth24plus, depth24plus-stencil8, and depth32float-stencil8 is added. .filter(t => isEncodableTextureFormat(t.format)) + .combine('filt', ['nearest', 'linear'] as const) .combine('mode', kShortAddressModes) .combine('offset', [false, true] as const) .beginSubcases() @@ -286,7 +305,7 @@ Parameters: .combine('compare', kCompareFunctions) ) .fn(async t => { - const { format, C, stage, samplePoints, mode, compare, offset } = t.params; + const { format, C, stage, samplePoints, mode, compare, filt: minFilter, offset } = t.params; const size = chooseTextureSize({ minSize: 8, minBlocks: 4, format }); const descriptor: GPUTextureDescriptor = { @@ -301,6 +320,9 @@ Parameters: addressModeU: kShortAddressModeToAddressMode[mode], addressModeV: kShortAddressModeToAddressMode[mode], compare, + minFilter, + magFilter: minFilter, + mipmapFilter: minFilter, }; const calls: TextureCall[] = generateTextureBuiltinInputs2D(50, { @@ -310,7 +332,7 @@ Parameters: descriptor, offset, depthRef: true, - hashInputs: [stage, format, C, samplePoints, mode, compare, offset], + hashInputs: [stage, format, C, samplePoints, mode, minFilter, compare, offset], }).map(({ coords, depthRef, offset }) => { return { builtin: 'textureGatherCompare', @@ -365,13 +387,14 @@ Parameters: .filter(t => isDepthTextureFormat(t.format)) // MAINTENANCE_TODO: Remove when support for depth24plus, depth24plus-stencil8, and depth32float-stencil8 is added. .filter(t => isEncodableTextureFormat(t.format)) + .combine('filt', ['nearest', 'linear'] as const) .combine('mode', kShortAddressModes) .beginSubcases() .combine('samplePoints', kCubeSamplePointMethods) .combine('compare', kCompareFunctions) ) .fn(async t => { - const { format, stage, samplePoints, mode, compare } = t.params; + const { format, stage, samplePoints, mode, filt: minFilter, compare } = t.params; const viewDimension: GPUTextureViewDimension = 'cube'; const size = chooseTextureSize({ minSize: 8, minBlocks: 2, format, viewDimension }); @@ -390,6 +413,9 @@ Parameters: addressModeV: kShortAddressModeToAddressMode[mode], addressModeW: kShortAddressModeToAddressMode[mode], compare, + minFilter, + magFilter: minFilter, + mipmapFilter: minFilter, }; const calls: TextureCall[] = generateSamplePointsCube(50, { @@ -398,7 +424,7 @@ Parameters: descriptor, depthRef: true, textureBuiltin: 'textureGatherCompare', - hashInputs: [stage, format, samplePoints, mode, compare], + hashInputs: [stage, format, samplePoints, mode, minFilter, compare], }).map(({ coords, depthRef }) => { return { builtin: 'textureGatherCompare', diff --git a/src/webgpu/shader/execution/expression/call/builtin/texture_utils.ts b/src/webgpu/shader/execution/expression/call/builtin/texture_utils.ts index 57c422cb6757..90d2f937126c 100644 --- a/src/webgpu/shader/execution/expression/call/builtin/texture_utils.ts +++ b/src/webgpu/shader/execution/expression/call/builtin/texture_utils.ts @@ -3,6 +3,7 @@ import { assert, range, unreachable } from '../../../../../../common/util/util.j import { Float16Array } from '../../../../../../external/petamoriken/float16/float16.js'; import { EncodableTextureFormat, + is32Float, isCompressedFloatTextureFormat, isCompressedTextureFormat, isDepthOrStencilTextureFormat, @@ -107,9 +108,6 @@ export function getTextureTypeForTextureViewDimension(viewDimension: GPUTextureV } } -const is32Float = (format: GPUTextureFormat) => - format === 'r32float' || format === 'rg32float' || format === 'rgba32float'; - const isUnencodableDepthFormat = (format: GPUTextureFormat) => format === 'depth24plus' || format === 'depth24plus-stencil8' || @@ -4729,12 +4727,11 @@ ${stageWGSL} } if (sampler) { + const type = isCompare ? 'comparison' : isFiltering ? 'filtering' : 'non-filtering'; entries.push({ binding: 1, visibility, - sampler: { - type: isCompare ? 'comparison' : isFiltering ? 'filtering' : 'non-filtering', - }, + sampler: { type }, }); }