export const description = ` Tests execution of render bundles. `; import { makeTestGroup } from '../../../../common/framework/test_group.js'; import { kDepthStencilFormats } from '../../../format_info.js'; import { AllFeaturesMaxLimitsGPUTest } from '../../../gpu_test.js'; export const g = makeTestGroup(AllFeaturesMaxLimitsGPUTest); g.test('empty_bundle_list') .desc( ` Test that it is valid to execute an empty list of render bundles ` ) .fn(t => { const encoder = t.createEncoder('render pass'); encoder.encoder.executeBundles([]); encoder.validateFinish(true); }); g.test('device_mismatch') .desc( ` Tests executeBundles cannot be called with render bundles created from another device Test with two bundles to make sure all bundles can be validated: - bundle0 and bundle1 from same device - bundle0 and bundle1 from different device ` ) .paramsSubcasesOnly([ { bundle0Mismatched: false, bundle1Mismatched: false }, // control case { bundle0Mismatched: true, bundle1Mismatched: false }, { bundle0Mismatched: false, bundle1Mismatched: true }, ]) .beforeAllSubcases(t => t.usesMismatchedDevice()) .fn(t => { const { bundle0Mismatched, bundle1Mismatched } = t.params; const descriptor: GPURenderBundleEncoderDescriptor = { colorFormats: ['rgba8unorm'], }; const bundle0Device = bundle0Mismatched ? t.mismatchedDevice : t.device; const bundle0 = bundle0Device.createRenderBundleEncoder(descriptor).finish(); const bundle1Device = bundle1Mismatched ? t.mismatchedDevice : t.device; const bundle1 = bundle1Device.createRenderBundleEncoder(descriptor).finish(); const encoder = t.createEncoder('render pass'); encoder.encoder.executeBundles([bundle0, bundle1]); encoder.validateFinish(!(bundle0Mismatched || bundle1Mismatched)); }); g.test('color_formats_mismatch') .desc( ` Tests executeBundles cannot be called with render bundles that do match the colorFormats of the render pass. This includes: - formats don't match - formats match but are in a different order - formats match but there is a different count ` ) .params(u => u.combineWithParams([ { bundleFormats: ['bgra8unorm', 'rg8unorm'] as const, passFormats: ['bgra8unorm', 'rg8unorm'] as const, _compatible: true, }, // control case { bundleFormats: ['bgra8unorm', 'rg8unorm'] as const, passFormats: ['bgra8unorm', 'bgra8unorm'] as const, _compatible: false, }, { bundleFormats: ['bgra8unorm', 'rg8unorm'] as const, passFormats: ['rg8unorm', 'bgra8unorm'] as const, _compatible: false, }, { bundleFormats: ['bgra8unorm', 'rg8unorm', 'rgba8unorm'] as const, passFormats: ['rg8unorm', 'bgra8unorm'] as const, _compatible: false, }, { bundleFormats: ['bgra8unorm', 'rg8unorm'] as const, passFormats: ['rg8unorm', 'bgra8unorm', 'rgba8unorm'] as const, _compatible: false, }, ]) ) .fn(t => { const { bundleFormats, passFormats, _compatible } = t.params; const bundleEncoder = t.device.createRenderBundleEncoder({ colorFormats: bundleFormats, }); const bundle = bundleEncoder.finish(); const encoder = t.createEncoder('render pass', { attachmentInfo: { colorFormats: passFormats, }, }); encoder.encoder.executeBundles([bundle]); encoder.validateFinish(_compatible); }); g.test('depth_stencil_formats_mismatch') .desc( ` Tests executeBundles cannot be called with render bundles that do match the depthStencil of the render pass. This includes: - formats don't match - formats have matching depth or stencil aspects, but other aspects are missing ` ) .params(u => u.combineWithParams([ { bundleFormat: 'depth24plus', passFormat: 'depth24plus' }, // control case { bundleFormat: 'depth24plus', passFormat: 'depth16unorm' }, { bundleFormat: 'depth24plus', passFormat: 'depth24plus-stencil8' }, { bundleFormat: 'stencil8', passFormat: 'depth24plus-stencil8' }, ] as const) ) .fn(t => { const { bundleFormat, passFormat } = t.params; t.skipIfTextureFormatNotSupported(bundleFormat, passFormat); const compatible = bundleFormat === passFormat; const bundleEncoder = t.device.createRenderBundleEncoder({ colorFormats: [], depthStencilFormat: bundleFormat, }); const bundle = bundleEncoder.finish(); const encoder = t.createEncoder('render pass', { attachmentInfo: { colorFormats: [], depthStencilFormat: passFormat, }, }); encoder.encoder.executeBundles([bundle]); encoder.validateFinish(compatible); }); g.test('depth_stencil_readonly_mismatch') .desc( ` Tests executeBundles cannot be called with render bundles that do match the depthStencil readonly state of the render pass. ` ) .params(u => u .combine('depthStencilFormat', kDepthStencilFormats) .beginSubcases() .combine('bundleDepthReadOnly', [false, true]) .combine('bundleStencilReadOnly', [false, true]) .combine('passDepthReadOnly', [false, true]) .combine('passStencilReadOnly', [false, true]) ) .fn(t => { const { depthStencilFormat, bundleDepthReadOnly, bundleStencilReadOnly, passDepthReadOnly, passStencilReadOnly, } = t.params; t.skipIfTextureFormatNotSupported(depthStencilFormat); const compatible = (!passDepthReadOnly || bundleDepthReadOnly === passDepthReadOnly) && (!passStencilReadOnly || bundleStencilReadOnly === passStencilReadOnly); const bundleEncoder = t.device.createRenderBundleEncoder({ colorFormats: [], depthStencilFormat, depthReadOnly: bundleDepthReadOnly, stencilReadOnly: bundleStencilReadOnly, }); const bundle = bundleEncoder.finish(); const encoder = t.createEncoder('render pass', { attachmentInfo: { colorFormats: [], depthStencilFormat, depthReadOnly: passDepthReadOnly, stencilReadOnly: passStencilReadOnly, }, }); encoder.encoder.executeBundles([bundle]); encoder.validateFinish(compatible); }); g.test('sample_count_mismatch') .desc( ` Tests executeBundles cannot be called with render bundles that do match the sampleCount of the render pass. ` ) .params(u => u.combineWithParams([ { bundleSamples: 1, passSamples: 1 }, // control case { bundleSamples: 4, passSamples: 4 }, // control case { bundleFormat: 4, passFormat: 1 }, { bundleFormat: 1, passFormat: 4 }, ]) ) .fn(t => { const { bundleSamples, passSamples } = t.params; const compatible = bundleSamples === passSamples; const bundleEncoder = t.device.createRenderBundleEncoder({ colorFormats: ['bgra8unorm'], sampleCount: bundleSamples, }); const bundle = bundleEncoder.finish(); const encoder = t.createEncoder('render pass', { attachmentInfo: { colorFormats: ['bgra8unorm'], sampleCount: passSamples, }, }); encoder.encoder.executeBundles([bundle]); encoder.validateFinish(compatible); });