@@ -261,8 +261,8 @@ class F extends TextureTestMixin(GPUTest) {
261
261
rasterizationMask : number ,
262
262
pipeline : GPURenderPipeline ,
263
263
uniformBuffer : GPUBuffer ,
264
- colorTargetsCount : number = 1
265
- ) : { color : GPUTexture ; depthStencil : GPUTexture } {
264
+ colorTargets : Iterable < GPUColorTargetState | null >
265
+ ) : { colors : ( GPUTexture | null ) [ ] ; depthStencil : GPUTexture } {
266
266
assert ( this . sampleTexture !== undefined ) ;
267
267
assert ( this . sampler !== undefined ) ;
268
268
@@ -286,37 +286,42 @@ class F extends TextureTestMixin(GPUTest) {
286
286
] ,
287
287
} ) ;
288
288
289
- const renderTargetTextures = [ ] ;
289
+ const renderTargetTextures : ( GPUTexture | null ) [ ] = [ ] ;
290
290
const resolveTargetTextures : ( GPUTexture | null ) [ ] = [ ] ;
291
- for ( let i = 0 ; i < colorTargetsCount ; i ++ ) {
292
- const renderTargetTexture = this . device . createTexture ( {
293
- format,
294
- size : {
295
- width : kRenderTargetSize ,
296
- height : kRenderTargetSize ,
297
- depthOrArrayLayers : 1 ,
298
- } ,
299
- sampleCount,
300
- mipLevelCount : 1 ,
301
- usage : GPUTextureUsage . RENDER_ATTACHMENT | GPUTextureUsage . TEXTURE_BINDING ,
302
- } ) ;
303
- renderTargetTextures . push ( renderTargetTexture ) ;
304
-
305
- const resolveTargetTexture =
306
- sampleCount === 1
307
- ? null
308
- : this . device . createTexture ( {
309
- format,
310
- size : {
311
- width : kRenderTargetSize ,
312
- height : kRenderTargetSize ,
313
- depthOrArrayLayers : 1 ,
314
- } ,
315
- sampleCount : 1 ,
316
- mipLevelCount : 1 ,
317
- usage : GPUTextureUsage . COPY_SRC | GPUTextureUsage . RENDER_ATTACHMENT ,
318
- } ) ;
319
- resolveTargetTextures . push ( resolveTargetTexture ) ;
291
+ for ( const target of colorTargets ) {
292
+ if ( target === null ) {
293
+ renderTargetTextures . push ( null ) ;
294
+ resolveTargetTextures . push ( null ) ;
295
+ } else {
296
+ const renderTargetTexture = this . device . createTexture ( {
297
+ format,
298
+ size : {
299
+ width : kRenderTargetSize ,
300
+ height : kRenderTargetSize ,
301
+ depthOrArrayLayers : 1 ,
302
+ } ,
303
+ sampleCount,
304
+ mipLevelCount : 1 ,
305
+ usage : GPUTextureUsage . RENDER_ATTACHMENT | GPUTextureUsage . TEXTURE_BINDING ,
306
+ } ) ;
307
+ renderTargetTextures . push ( renderTargetTexture ) ;
308
+
309
+ const resolveTargetTexture =
310
+ sampleCount === 1
311
+ ? null
312
+ : this . device . createTexture ( {
313
+ format,
314
+ size : {
315
+ width : kRenderTargetSize ,
316
+ height : kRenderTargetSize ,
317
+ depthOrArrayLayers : 1 ,
318
+ } ,
319
+ sampleCount : 1 ,
320
+ mipLevelCount : 1 ,
321
+ usage : GPUTextureUsage . COPY_SRC | GPUTextureUsage . RENDER_ATTACHMENT ,
322
+ } ) ;
323
+ resolveTargetTextures . push ( resolveTargetTexture ) ;
324
+ }
320
325
}
321
326
322
327
const depthStencilTexture = this . device . createTexture ( {
@@ -331,6 +336,10 @@ class F extends TextureTestMixin(GPUTest) {
331
336
332
337
const renderPassDescriptor : GPURenderPassDescriptor = {
333
338
colorAttachments : renderTargetTextures . map ( ( renderTargetTexture , index ) => {
339
+ if ( renderTargetTexture === null ) {
340
+ return null ;
341
+ }
342
+
334
343
return {
335
344
view : renderTargetTexture . createView ( ) ,
336
345
resolveTarget : resolveTargetTextures [ index ] ?. createView ( ) ,
@@ -383,7 +392,7 @@ class F extends TextureTestMixin(GPUTest) {
383
392
this . device . queue . submit ( [ commandEncoder . finish ( ) ] ) ;
384
393
385
394
return {
386
- color : renderTargetTextures [ 0 ] ,
395
+ colors : renderTargetTextures ,
387
396
depthStencil : depthStencilTexture ,
388
397
} ;
389
398
}
@@ -514,6 +523,7 @@ textureLoad each sample index from the texture and write to a storage buffer to
514
523
new Uint32Array ( [ fragmentShaderOutputMask ] )
515
524
) ;
516
525
526
+ const colorTargets = [ { format } ] as const ;
517
527
const pipeline = t . device . createRenderPipeline ( {
518
528
layout : 'auto' ,
519
529
vertex : {
@@ -540,7 +550,7 @@ textureLoad each sample index from the texture and write to a storage buffer to
540
550
}` ,
541
551
} ) ,
542
552
entryPoint : 'main' ,
543
- targets : [ { format } ] ,
553
+ targets : colorTargets ,
544
554
} ,
545
555
primitive : { topology : 'triangle-list' } ,
546
556
multisample : {
@@ -564,12 +574,15 @@ textureLoad each sample index from the texture and write to a storage buffer to
564
574
} ,
565
575
} ) ;
566
576
567
- const { color , depthStencil } = t . GetTargetTexture (
577
+ const { colors , depthStencil } = t . GetTargetTexture (
568
578
sampleCount ,
569
579
rasterizationMask ,
570
580
pipeline ,
571
- fragmentMaskUniformBuffer
581
+ fragmentMaskUniformBuffer ,
582
+ colorTargets
572
583
) ;
584
+ const color = colors [ 0 ] ;
585
+ assert ( color !== null ) ;
573
586
574
587
t . CheckColorAttachmentResult (
575
588
color ,
@@ -601,12 +614,13 @@ textureLoad each sample index from the texture and write to a storage buffer to
601
614
g . test ( 'alpha_to_coverage_mask' )
602
615
. desc (
603
616
`
604
- Test that alpha_to_coverage_mask is working properly with the alpha output of color target[0].
617
+ Test that alpha_to_coverage_mask is working properly with the shader alpha output of color target[0].
605
618
606
619
- for sampleCount = 4, alphaToCoverageEnabled = true and various combinations of:
607
620
- rasterization masks
608
621
- increasing alpha0 values of the color0 output including { < 0, = 0, = 1/16, = 2/16, ..., = 15/16, = 1, > 1 }
609
- - alpha1 values of the color1 output = { 0, 0.5, 1.0 }.
622
+ - unrelated alpha1 values of the color1 output = { 0, 0.5, 1.0 } (when target[0] is not empty) or = { 1.0 } (when target[0] is empty)
623
+ - target[0] is empty or not
610
624
- test that for a single pixel in { color0, color1 } { color0, depth, stencil } output the final sample mask is applied to it, moreover:
611
625
- if alpha0 is 0.0 or less then alpha to coverage mask is 0x0,
612
626
- if alpha0 is 1.0 or greater then alpha to coverage mask is 0xFFFFFFFF,
@@ -622,18 +636,31 @@ color' <= color.
622
636
)
623
637
. params ( u =>
624
638
u
639
+ . combine ( 'hasSparseColorAttachment' , [ false , true ] as const )
625
640
. expand ( 'rasterizationMask' , function * ( p ) {
626
641
for ( let i = 0 , len = 0xf ; i <= len ; i ++ ) {
627
642
yield i ;
628
643
}
629
644
} )
630
645
. beginSubcases ( )
631
- . combine ( 'alpha1' , [ 0.0 , 0.5 , 1.0 ] as const )
646
+ . expand ( 'alpha1' , p => {
647
+ if ( p . hasSparseColorAttachment ) {
648
+ // when hasSparseColorAttachment is true
649
+ // target[0] is empty but target[0].a is still used as alphaToCoverage value.
650
+ // target[1] is used as the color output, so target[1].a stays at 1.0 to match sample texture values.
651
+ return [ 1.0 ] ;
652
+ }
653
+ return [ 0.0 , 0.5 , 1.0 ] ;
654
+ } )
632
655
)
633
656
. fn ( async t => {
634
657
const sampleCount = 4 ;
635
658
const sampleMask = 0xffffffff ;
636
- const { rasterizationMask, alpha1 } = t . params ;
659
+ const { hasSparseColorAttachment, rasterizationMask, alpha1 } = t . params ;
660
+ const colorTargets = [
661
+ hasSparseColorAttachment ? null : ( { format } as const ) ,
662
+ { format } ,
663
+ ] as const ;
637
664
638
665
const alphaValues = new Float32Array ( 4 ) ; // [alpha0, alpha1, 0, 0]
639
666
const alphaValueUniformBuffer = t . device . createBuffer ( {
@@ -674,7 +701,7 @@ color' <= color.
674
701
}` ,
675
702
} ) ,
676
703
entryPoint : 'main' ,
677
- targets : [ { format } , { format } ] ,
704
+ targets : colorTargets ,
678
705
} ,
679
706
primitive : { topology : 'triangle-list' } ,
680
707
multisample : {
@@ -699,25 +726,29 @@ color' <= color.
699
726
} ) ;
700
727
701
728
// { < 0, = 0, = 1/16, = 2/16, ..., = 15/16, = 1, > 1 }
702
- const alpha0ParamsArray = [ - 0.1 , ...range ( 16 , i => i / 16 ) , 1.0 , 1.1 ] ;
729
+ const alphaParamsArray = [ - 0.1 , ...range ( 16 , i => i / 16 ) , 1.0 , 1.1 ] ;
703
730
704
731
const colorResultPromises = [ ] ;
705
732
const depthResultPromises = [ ] ;
706
733
const stencilResultPromises = [ ] ;
707
734
708
- for ( const alpha0 of alpha0ParamsArray ) {
735
+ for ( const alpha0 of alphaParamsArray ) {
709
736
alphaValues [ 0 ] = alpha0 ;
710
737
alphaValues [ 1 ] = alpha1 ;
738
+
711
739
t . device . queue . writeBuffer ( alphaValueUniformBuffer , 0 , alphaValues ) ;
712
740
713
- const { color , depthStencil } = t . GetTargetTexture (
741
+ const { colors , depthStencil } = t . GetTargetTexture (
714
742
sampleCount ,
715
743
rasterizationMask ,
716
744
pipeline ,
717
745
alphaValueUniformBuffer ,
718
- 2
746
+ colorTargets
719
747
) ;
720
748
749
+ const color = hasSparseColorAttachment ? colors [ 1 ] : colors [ 0 ] ;
750
+ assert ( color !== null ) ;
751
+
721
752
const colorBuffer = t . copySinglePixelTextureToBufferUsingComputePass (
722
753
TypeF32 , // correspond to 'rgba8unorm' format
723
754
4 ,
@@ -776,13 +807,13 @@ color' <= color.
776
807
) => {
777
808
for ( let i = 0 ; i < results . length ; i ++ ) {
778
809
const result = results [ i ] ;
779
- const alpha0 = alpha0ParamsArray [ i ] ;
810
+ const alpha = alphaParamsArray [ i ] ;
780
811
781
- if ( alpha0 <= 0 ) {
812
+ if ( alpha <= 0 ) {
782
813
const expected = getExpectedDataFn ( sampleCount , rasterizationMask , sampleMask , 0x0 ) ;
783
814
const check = checkElementsEqual ( result . data , expected ) ;
784
815
t . expectOK ( check ) ;
785
- } else if ( alpha0 >= 1 ) {
816
+ } else if ( alpha >= 1 ) {
786
817
const expected = getExpectedDataFn (
787
818
sampleCount ,
788
819
rasterizationMask ,
0 commit comments