Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion src/webgpu/api/validation/createTexture.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,11 @@ g.test('sampleCount,valid_sampleCount_with_other_parameter_varies')
dimension !== '2d')) ||
((usage & GPUConst.TextureUsage.STORAGE_BINDING) !== 0 &&
!isTextureFormatPossiblyStorageReadable(format)) ||
(mipLevelCount !== 1 && dimension === '1d')
(mipLevelCount !== 1 && dimension === '1d') ||
((usage & GPUConst.TextureUsage.TRANSIENT_ATTACHMENT) !== 0 &&
usage !==
(GPUConst.TextureUsage.RENDER_ATTACHMENT |
GPUConst.TextureUsage.TRANSIENT_ATTACHMENT))
);
})
)
Expand Down Expand Up @@ -1037,6 +1041,11 @@ g.test('texture_usage')
if (isColorTextureFormat(format) && !isTextureFormatColorRenderable(t.device, format))
success = false;
}
if (usage & GPUTextureUsage.TRANSIENT_ATTACHMENT) {
if (usage !== (GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TRANSIENT_ATTACHMENT)) {
success = false;
}
}

t.expectValidationError(() => {
t.createTextureTracked(descriptor);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,48 @@ g.test('attachments,mip_level_count')
}
});

g.test('color_attachments,loadOp_storeOp')
.desc(
`
Test GPURenderPassColorAttachment Usage:
- if usage includes TRANSIENT_ATTACHMENT
- loadOp must be clear
- storeOp must be discard
`
)
.params(u =>
u
.combine('format', kPossibleColorRenderableTextureFormats)
.beginSubcases()
.combine('transientTexture', [true, false])
.combine('loadOp', ['clear', 'load'] as GPULoadOp[])
.combine('storeOp', ['discard', 'store'] as GPUStoreOp[])
)
.fn(t => {
const { format, transientTexture, loadOp, storeOp } = t.params;

t.skipIfTextureFormatNotSupported(format);
t.skipIfTextureFormatNotUsableAsRenderAttachment(format);

const usage = transientTexture
? GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TRANSIENT_ATTACHMENT
: GPUTextureUsage.RENDER_ATTACHMENT;

const texture = t.createTestTexture({ usage });

const colorAttachment = t.getColorAttachment(texture);
colorAttachment.loadOp = loadOp;
colorAttachment.storeOp = storeOp;

const passDescriptor: GPURenderPassDescriptor = {
colorAttachments: [colorAttachment],
};

const success = !transientTexture || (loadOp === 'clear' && storeOp === 'discard');

t.tryRenderPass(success, passDescriptor);
});

g.test('color_attachments,non_multisampled')
.desc(
`
Expand Down Expand Up @@ -1039,22 +1081,28 @@ g.test('depth_stencil_attachment,loadOp_storeOp_match_depthReadOnly_stencilReadO
.desc(
`
Test GPURenderPassDepthStencilAttachment Usage:
- if the format has a depth aspect:
- if depthReadOnly is true
- depthLoadOp and depthStoreOp must not be provided
- else:
- depthLoadOp and depthStoreOp must be provided
- if the format has a stencil aspect:
- if stencilReadOnly is true
- stencilLoadOp and stencilStoreOp must not be provided
- else:
- stencilLoadOp and stencilStoreOp must be provided
- if the format has a depth aspect and depthReadOnly is false
- depthLoadOp and depthStoreOp must be provided
- else:
- depthLoadOp and depthStoreOp must not be provided
- if the format has a stencil aspect and stencilReadOnly is false
- stencilLoadOp and stencilStoreOp must be provided
- else:
- stencilLoadOp and stencilStoreOp must not be provided
- if usage includes TRANSIENT_ATTACHMENT
- if the format has a depth aspect:
- depthLoadOp must be clear
- depthStoreOp must be discard
- if the format has a stencil aspect:
- stencilLoadOp must be clear
- stencilStoreOp must be discard
`
)
.params(u =>
u
.combine('format', kDepthStencilFormats)
.beginSubcases() // Note: It's easier to debug if you comment this line out as you can then run an individual case.
.combine('transientTexture', [true, false])
.combine('depthReadOnly', [undefined, true, false])
.combine('depthLoadOp', [undefined, 'clear', 'load'] as GPULoadOp[])
.combine('depthStoreOp', [undefined, 'discard', 'store'] as GPUStoreOp[])
Expand All @@ -1065,6 +1113,7 @@ g.test('depth_stencil_attachment,loadOp_storeOp_match_depthReadOnly_stencilReadO
.fn(t => {
const {
format,
transientTexture,
depthReadOnly,
depthLoadOp,
depthStoreOp,
Expand All @@ -1075,10 +1124,13 @@ g.test('depth_stencil_attachment,loadOp_storeOp_match_depthReadOnly_stencilReadO

t.skipIfTextureFormatNotSupported(format);

const usage = transientTexture
? GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TRANSIENT_ATTACHMENT
: GPUTextureUsage.RENDER_ATTACHMENT;
const depthAttachment = t.createTextureTracked({
format,
size: { width: 1, height: 1, depthOrArrayLayers: 1 },
usage: GPUTextureUsage.RENDER_ATTACHMENT,
usage,
});
const depthAttachmentView = depthAttachment.createView();

Expand Down Expand Up @@ -1120,7 +1172,13 @@ g.test('depth_stencil_attachment,loadOp_storeOp_match_depthReadOnly_stencilReadO
const goodStencilCombo =
hasStencil && !stencilReadOnly ? hasBothStencilOps : hasNeitherStencilOps;

const shouldError = !goodAspectSettingsPresent || !goodDepthCombo || !goodStencilCombo;
const goodTransient =
!transientTexture ||
((!hasDepth || (depthLoadOp === 'clear' && depthStoreOp === 'discard')) &&
(!hasStencil || (stencilLoadOp === 'clear' && stencilStoreOp === 'discard')));

const shouldError =
!goodAspectSettingsPresent || !goodDepthCombo || !goodStencilCombo || !goodTransient;

t.expectValidationError(() => {
encoder.finish();
Expand Down
1 change: 1 addition & 0 deletions src/webgpu/capability_info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ export const kTextureUsageInfo: {
[GPUConst.TextureUsage.TEXTURE_BINDING]: {},
[GPUConst.TextureUsage.STORAGE_BINDING]: {},
[GPUConst.TextureUsage.RENDER_ATTACHMENT]: {},
[GPUConst.TextureUsage.TRANSIENT_ATTACHMENT]: {},
};
/** List of all GPUTextureUsage values. */
export const kTextureUsages = numericKeysOf<GPUTextureUsageFlags>(kTextureUsageInfo);
Expand Down
8 changes: 8 additions & 0 deletions src/webgpu/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ const BufferUsage = {
} as const;
checkType<typeof GPUBufferUsage>(BufferUsage);

declare global {
// MAINTENANCE_TODO: Remove this once TRANSIENT_ATTACHMENT is added to @webgpu/types
interface GPUTextureUsage {
readonly TRANSIENT_ATTACHMENT: GPUFlagsConstant;
}
}

const TextureUsage = {
COPY_SRC: 0x01,
COPY_DST: 0x02,
Expand All @@ -25,6 +32,7 @@ const TextureUsage = {
STORAGE_BINDING: 0x08,
STORAGE: 0x08,
RENDER_ATTACHMENT: 0x10,
TRANSIENT_ATTACHMENT: 0x20,
} as const;
checkType<typeof GPUTextureUsage>(TextureUsage);

Expand Down
1 change: 1 addition & 0 deletions src/webgpu/idl/constants/flags.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const kTextureUsageExp = {
TEXTURE_BINDING: 0x04,
STORAGE_BINDING: 0x08,
RENDER_ATTACHMENT: 0x10,
TRANSIENT_ATTACHMENT: 0x20,
};
g.test('TextureUsage,count').fn(t => {
t.assertMemberCount(GPUTextureUsage, kTextureUsageExp);
Expand Down