@@ -26,7 +26,12 @@ import {
2626 makeRandomDepthComparisonTexelGenerator ,
2727 queryMipLevelMixWeightsForDevice ,
2828 readTextureToTexelViews ,
29+ SoftwareTexture ,
30+ softwareTextureRead ,
31+ swizzleTexel ,
2932 texelsApproximatelyEqual ,
33+ TextureCall ,
34+ vec2 ,
3035} from './texture_utils.js' ;
3136
3237export const g = makeTestGroup ( AllFeaturesMaxLimitsGPUTest ) ;
@@ -325,3 +330,106 @@ are supposed to work around this issue by poly-filling on devices that fail this
325330 validateWeights ( t , stage , 'textureSampleLevel' , weights . sampleLevelWeights ) ;
326331 validateWeights ( t , stage , 'textureSampleGrad' , weights . softwareMixToGPUMixGradWeights ) ;
327332 } ) ;
333+
334+ g . test ( 'softwareSamplerSwizzle' )
335+ . desc ( 'test the software sampler swizzles' )
336+ . params ( u =>
337+ u
338+ . combine ( 'srcFormat' , [ 'rgba8unorm' , 'bgra8unorm' , 'depth24plus' , 'stencil8' ] as const )
339+ . beginSubcases ( )
340+ . combine ( 'swizzle' , [ 'rgba' , 'abgr' , '10gr' ] as const )
341+ . expand ( 'textureType' , function * ( t ) {
342+ const type = getTextureFormatType ( t . srcFormat , 'all' ) ;
343+ switch ( type ) {
344+ case 'depth' :
345+ yield 'texture_2d<f32>' ;
346+ yield 'texture_depth_2d' ;
347+ break ;
348+ case 'uint' :
349+ yield 'texture_2d<u32>' ;
350+ break ;
351+ case 'sint' :
352+ yield 'texture_2d<i32>' ;
353+ break ;
354+ default :
355+ yield 'texture_2d<f32>' ;
356+ }
357+ } )
358+ )
359+ . fn ( async t => {
360+ t . skipIfDeviceDoesNotHaveFeature ( 'texture-component-swizzle' ) ;
361+
362+ const { srcFormat, swizzle, textureType } = t . params ;
363+ const size = chooseTextureSize ( { minSize : 9 , minBlocks : 4 , format : srcFormat } ) ;
364+ t . debug ( `size: ${ size . map ( v => v . toString ( ) ) . join ( ', ' ) } ` ) ;
365+ const descriptor : GPUTextureDescriptor = {
366+ format : srcFormat ,
367+ size,
368+ usage : GPUTextureUsage . COPY_DST | GPUTextureUsage . TEXTURE_BINDING ,
369+ } ;
370+ const { texels, texture } = await createTextureWithRandomDataAndGetTexels ( t , descriptor ) ;
371+
372+ const viewDescriptor = { swizzle } ;
373+ const softwareTexture : SoftwareTexture = {
374+ texels,
375+ descriptor,
376+ viewDescriptor,
377+ } ;
378+ const call : TextureCall < vec2 > = {
379+ builtin : 'textureLoad' ,
380+ coordType : 'u' ,
381+ mipLevel : 0 ,
382+ coords : [ 0 , 0 ] ,
383+ } ;
384+
385+ const type = getTextureFormatType ( srcFormat , 'all' ) ;
386+ const resultFormat =
387+ type === 'uint' ? 'rgba32uint' : type === 'sint' ? 'rgba32sint' : 'rgba32float' ;
388+
389+ const aspect = srcFormat === 'stencil8' ? 'stencil-only' : 'all' ;
390+
391+ // For each pixel in the texelView, convert it to RGBA and swizzle.
392+ // Then, call softwareTextureRead for that texel. The results should
393+ // be the same.
394+ const stage = 'compute' ;
395+ const errors = [ ] ;
396+ for ( let mipLevel = 0 ; mipLevel < texels . length ; ++ mipLevel ) {
397+ const expectedMipLevelTexelView = texels [ mipLevel ] ;
398+ const mipLevelSize = virtualMipSize ( texture . dimension , size , mipLevel ) ;
399+ const rep = kTexelRepresentationInfo [ expectedMipLevelTexelView . format ] ;
400+
401+ for ( let y = 0 ; y < mipLevelSize [ 1 ] ; ++ y ) {
402+ for ( let x = 0 ; x < mipLevelSize [ 0 ] ; ++ x ) {
403+ const expectedRaw = expectedMipLevelTexelView . color ( { x, y, z : 0 } ) ;
404+ const expectedRGBA = convertPerTexelComponentToResultFormat (
405+ expectedRaw ,
406+ resultFormat ,
407+ aspect
408+ ) ;
409+ const expected = swizzleTexel ( expectedRGBA , swizzle ) ;
410+ call . coords = [ x , y ] ;
411+ call . mipLevel = mipLevel ;
412+ const actual = softwareTextureRead < vec2 > ( t , stage , call , softwareTexture ) ;
413+ const maxFractionalDiff = 0 ;
414+ if (
415+ ! texelsApproximatelyEqual (
416+ t . device ,
417+ call . builtin ,
418+ textureType ,
419+ actual ,
420+ resultFormat ,
421+ expected ,
422+ resultFormat ,
423+ maxFractionalDiff
424+ )
425+ ) {
426+ const actualStr = texelFormat ( actual , rep ) ;
427+ const expectedStr = texelFormat ( expected , rep ) ;
428+ errors . push ( `texel at ${ x } , ${ y } , expected: ${ expectedStr } , actual: ${ actualStr } ` ) ;
429+ }
430+ }
431+ }
432+
433+ assert ( errors . length === 0 , errors . join ( '\n' ) ) ;
434+ }
435+ } ) ;
0 commit comments