@@ -7,6 +7,8 @@ Note: entry point matching tests are in shader_module/entry_point.spec.ts
77import { AllFeaturesMaxLimitsGPUTest } from '../.././gpu_test.js' ;
88import { makeTestGroup } from '../../../common/framework/test_group.js' ;
99import { keysOf } from '../../../common/util/data_tables.js' ;
10+ import { getGPU } from '../../../common/util/navigator_gpu.js' ;
11+ import { supportsImmediateData } from '../../../common/util/util.js' ;
1012import {
1113 isTextureFormatUsableWithStorageAccessMode ,
1214 kPossibleStorageTextureFormats ,
@@ -811,3 +813,71 @@ generates a validation error at createComputePipeline(Async)
811813 } ;
812814 vtu . doCreateComputePipelineTest ( t , isAsync , success , descriptor ) ;
813815 } ) ;
816+
817+ g . test ( 'pipeline_creation_immediate_size_mismatch' )
818+ . desc (
819+ `
820+ Validate that creating a pipeline fails if the shader uses immediate data
821+ larger than the immediateSize specified in the pipeline layout, or larger than
822+ maxImmediateSize if layout is 'auto'.
823+ Also validates that using less or equal size is allowed.
824+ `
825+ )
826+ . params ( u =>
827+ u . combine ( 'isAsync' , [ true , false ] ) . combineWithParams ( [
828+ { shaderSize : 16 , layoutSize : 16 } , // Equal
829+ { shaderSize : 12 , layoutSize : 16 } , // Shader smaller
830+ { shaderSize : 20 , layoutSize : 16 } , // Shader larger (small diff)
831+ { shaderSize : 32 , layoutSize : 16 } , // Shader larger
832+ { shaderSize : 'max' , layoutSize : 'auto' } , // Shader equal to limit (auto layout)
833+ { shaderSize : 'max+4' , layoutSize : 'auto' } , // Shader larger than limit (auto layout)
834+ ] as const )
835+ )
836+ . fn ( t => {
837+ if ( ! supportsImmediateData ( getGPU ( t . rec ) ) ) {
838+ t . skip ( 'Immediate data not supported' ) ;
839+ }
840+
841+ const { isAsync, shaderSize, layoutSize } = t . params ;
842+
843+ const maxImmediateSize = t . device . limits . maxImmediateSize ! ;
844+
845+ let actualLayout : GPUPipelineLayout | 'auto' ;
846+ let validSize : number ;
847+
848+ if ( layoutSize === 'auto' ) {
849+ actualLayout = 'auto' ;
850+ // checked above
851+ validSize = maxImmediateSize ! ;
852+ } else {
853+ actualLayout = t . device . createPipelineLayout ( {
854+ bindGroupLayouts : [ ] ,
855+ immediateSize : layoutSize as number ,
856+ } ) ;
857+ validSize = layoutSize as number ;
858+ }
859+
860+ let actualShaderSize : number ;
861+ if ( shaderSize === 'max' ) {
862+ actualShaderSize = validSize ;
863+ } else if ( shaderSize === 'max+4' ) {
864+ actualShaderSize = validSize + 4 ;
865+ } else {
866+ actualShaderSize = shaderSize as number ;
867+ }
868+
869+ const code = `
870+ var<immediate> data: array<u32, ${ actualShaderSize / 4 } >;
871+ fn use() { _ = data[0]; }
872+ @compute @workgroup_size(1) fn main_compute() { use(); }
873+ ` ;
874+
875+ const shouldError = actualShaderSize > validSize ;
876+
877+ vtu . doCreateComputePipelineTest ( t , isAsync , ! shouldError , {
878+ layout : actualLayout ,
879+ compute : {
880+ module : t . device . createShaderModule ( { code } ) ,
881+ } ,
882+ } ) ;
883+ } ) ;
0 commit comments