From 03da857a87c78a951208b3e1ce2fe993efa2231e Mon Sep 17 00:00:00 2001 From: Jiawei Shao Date: Thu, 9 Apr 2020 03:32:10 +0800 Subject: [PATCH] Add validation rules for copyBufferToTexture (#648) * Add validation rules for copyBufferToTexture * Small fix * Address more reviewer's suggestions * Address more comments from the reviewers * Fix several typos --- spec/index.bs | 157 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 142 insertions(+), 15 deletions(-) diff --git a/spec/index.bs b/spec/index.bs index dc522d683e..1ac0991537 100644 --- a/spec/index.bs +++ b/spec/index.bs @@ -2434,26 +2434,35 @@ dictionary GPUBufferCopyView { A {{GPUBufferCopyView}} is a view of a [=buffer=] as an array of images, used when copying data between a [=texture=] and a [=buffer=]. - - For {{GPUTextureDimension/2d}} textures, data is copied between one [=image=] and one [=array layer=]. - - For {{GPUTextureDimension/3d}} textures, data is copied between one [=image=] and one depth [=slice=]. + - For {{GPUTextureDimension/2d}} textures, data is copied between one or multiple contiguous [=images=] and [=array layers=]. + - For {{GPUTextureDimension/3d}} textures, data is copied between one or multiple contiguous [=images=] and depth [=slices=]. + +Issue: Define images more precisely. In particular, define them as being comprised of [=texel blocks=]. + +Issue: Define the exact copy semantics, by reference to common algorithms shared by the copy methods.
: bytesPerRow :: - The stride, in bytes, between the beginning of each row of data and - the subsequent row. + The stride, in bytes, between the beginning of each row of [=texel blocks=] and the subsequent row. : rowsPerImage :: - {{GPUBufferCopyView/rowsPerImage}} × {{GPUBufferCopyView/bytesPerRow}} - is the stride, in bytes, between the beginning of each [=image=] of data - and the subsequent [=image=]. - - Note: - {{GPUBufferCopyView/rowsPerImage}} must be zero for copies with a `copySize.depth` of 1, - and must be greater than zero otherwise. + {{GPUBufferCopyView/rowsPerImage}} ÷ [=texel block height=] × + {{GPUBufferCopyView/bytesPerRow}} is the stride, in bytes, between the beginning of each [=image=] + of data and the subsequent [=image=].
+
+ +GPUBufferCopyView Valid Usage + +Given a {{GPUBufferCopyView}} |bufferCopyView|, the following validation rules apply: + - |bufferCopyView|.{{GPUBufferCopyView/buffer}} must be a [=valid=] {{GPUBuffer}}. + - |bufferCopyView|.{{GPUBufferCopyView/bytesPerRow}} must be a multiple of 256. + +
+ ### GPUTextureCopyView ### {#gpu-texture-copy-view} -A {{GPUTextureCopyView}} is a view of a sub-region of a [=texture=] [=subresource=] with the initial offset {{GPUOrigin3D}} in -texels, used when copying data from or to a {{GPUTexture}}. - - - For {{GPUTextureDimension/2d}} textures, data is copied from or to one [=mipmap level=] and one [=array layer=] of the [=texture=]. +A {{GPUTextureCopyView}} is a view of a sub-region of one or multiple contiguous [=texture=] [=subresources=] with the initial +offset {{GPUOrigin3D}} in texels, used when copying data from or to a {{GPUTexture}}. * {{GPUTextureCopyView/origin}}: If unspecified, defaults to `[0, 0, 0]`. +
+ +GPUTextureCopyView Valid Usage + + Given a {{GPUTextureCopyView}} |textureCopyView|, let + - |blockWidth| be the [=texel block width=] of |textureCopyView|.{{GPUTextureCopyView/texture}}.{{GPUTexture/[[format]]}}. + - |blockHeight| be the [=texel block height=] of |textureCopyView|.{{GPUTextureCopyView/texture}}.{{GPUTexture/[[format]]}}. + + The following validation rules apply: + - |textureCopyView|.{{GPUTextureCopyView/texture}} must be a [=valid=] {{GPUTexture}}. + - The {{GPUTexture/[[sampleCount]]}} of |textureCopyView|.{{GPUTextureCopyView/texture}} must be 1. + - |textureCopyView|.{{GPUTextureCopyView/mipLevel}} must be less than the {{GPUTexture/[[mipLevelCount]]}} of + |textureCopyView|.{{GPUTextureCopyView/texture}}. + - If the |textureCopyView|.{{GPUTextureCopyView/texture}} is {{GPUTextureDimension/1d}} or {{GPUTextureDimension/3d}}: + - |textureCopyView|.{{GPUTextureCopyView/arrayLayer}} must be zero. + - |textureCopyView|.{{GPUTextureCopyView/origin}}.{{GPUOrigin3DDict/x}} must be a multiple of |blockWidth|. + - |textureCopyView|.{{GPUTextureCopyView/origin}}.{{GPUOrigin3DDict/y}} must be a multiple of |blockHeight|. + +
+ Issue(gpuweb/gpuweb#69): Define the copies with {{GPUTextureDimension/1d}} and {{GPUTextureDimension/3d}} textures. ### GPUImageBitmapCopyView ### {#gpu-image-bitmap-copy-view} @@ -2527,6 +2554,106 @@ dictionary GPUImageBitmapCopyView { +### copyBufferToTexture(source, destination, copySize) ### {#GPUCommandEncoder-copyBufferToTexture} + +
+ + **Arguments:** + - {{GPUBufferCopyView}} |source| + - {{GPUTextureCopyView}} |destination| + - {{GPUExtent3D}} |copySize| + + **Returns:** void + + Encode a command into the {{GPUCommandEncoder}} that copies data from a sub-region of a + {{GPUBuffer}} to a sub-region of one or multiple continuous {{GPUTexture}} [=subresources=]. + + |source| and |copySize| define the region of the source buffer. + + |destination| and |copySize| define the region of the destination texture [=subresource=]. + +
+ +
+ +copyBufferToTexture Valid Usage + +Given a {{GPUCommandEncoder}} |encoder| and the arguments {{GPUBufferCopyView}} |source|, +{{GPUTextureCopyView}} |destination|, {{GPUExtent3D}} |copySize|, let + - |blockWidth| be the [=texel block width=] of |destination|.{{GPUTextureCopyView/texture}}.{{GPUTexture/[[format]]}}. + - |blockHeight| be the [=texel block height=] of |destination|.{{GPUTextureCopyView/texture}}.{{GPUTexture/[[format]]}}. + - |blockSize| be the [=texel block size=] of |destination|.{{GPUTextureCopyView/texture}}.{{GPUTexture/[[format]]}}. + - |bytesInACompleteRow| be |blockSize| × |copySize|.[=Extent3D/width=] ÷ |blockWidth|. + - |bytesInACompleteImage| be |bytesInACompleteRow| × |copySize|.[=Extent3D/height=] ÷ |blockHeight|. + - |requiredBytesInCopy| be calculated with the following algorithm assuming all the parameters are [=valid=]: + ``` + if (copySize.width == 0 || copySize.height == 0 || copySize.depth == 0) { + requiredBytesInCopy = 0; + } else { + GPUSize64 texelBlockRowsPerImage = source.rowsPerImage / blockHeight; + GPUSize64 bytesPerImage = source.bytesPerRow * texelBlockRowsPerImage; + GPUSize64 bytesInLastSlice = + source.bytesPerRow * (copySize.height / blockHeight - 1) + (copySize.width / blockWidth * blockSize); + requiredBytesInCopy = bytesPerImage * (copySize.depth - 1) + bytesInLastSlice; + } + ``` + + The following validation rules apply: + + For |encoder|: + - |encoder|.{{GPUCommandEncoder/copyBufferToTexture()}} must not be called when a {{GPURenderPassEncoder}} + is active on |encoder|. + - |encoder|.{{GPUCommandEncoder/copyBufferToTexture()}} must not be called when a {{GPUComputePassEncoder}} + is active on |encoder|. + + For |source|: + - |source| must be [=valid=]. + - |source|.{{GPUBufferCopyView/buffer}}.{{GPUBuffer/[[usage]]}} must contain {{GPUBufferUsage/COPY_SRC}}. + + For |destination|: + - |destination| must be [=valid=]. + - |destination|.{{GPUTextureCopyView/texture}}.{{GPUTexture/[[textureUsage]]}} must contain + {{GPUTextureUsage/COPY_DST}}. + + For |copySize|: + - If the {{GPUTexture/[[dimension]]}} of |destination|.{{GPUTextureCopyView/texture}} is + {{GPUTextureDimension/1d}}: + - Both |copySize|.[=Extent3D/height=] and [=Extent3D/depth=] must be 1. + + For the copy being in-bounds: + - If |source|.{{GPUBufferCopyView/rowsPerImage}} is not 0, it must be greater than or equal to + |copySize|.[=Extent3D/height=]. + - (|source|.{{GPUBufferCopyView/offset}} &add; |requiredBytesInCopy|) must not overflow a {{GPUSize64}}. + - (|source|.{{GPUBufferCopyView/offset}} &add; |requiredBytesInCopy|) must be smaller than or equal to + |source|.{{GPUBufferCopyView/buffer}}.{{GPUBuffer/[[size]]}}. + - If the {{GPUTexture/[[dimension]]}} of |destination|.{{GPUTextureCopyView/texture}} is + {{GPUTextureDimension/2d}}: + - (|destination|.{{GPUTextureCopyView/origin}}.{{GPUOrigin3DDict/x}} &add; |copySize|.[=Extent3D/width=]) must be less than or equal to the width of the [=physical size=] of |destination|.{{GPUTextureCopyView/texture}} [=subresource=] at [=mipmap level=] {{GPUTextureCopyView/mipLevel}}. + - (|destination|.{{GPUTextureCopyView/origin}}.{{GPUOrigin3DDict/y}} &add; |copySize|.[=Extent3D/height=]) must be less than or equal to the height of the [=physical size=] of |destination|.{{GPUTextureCopyView/texture}} [=subresource=] at [=mipmap level=] {{GPUTextureCopyView/mipLevel}} + - (|destination|.{{GPUTextureCopyView/arrayLayer}} &add; |copySize|.[=Extent3D/depth=]) must be less than or equal to the depth of the [=Extent3D/depth=] of the |destination|.{{GPUTextureCopyView/texture}}. + + For the texel block alignments: + - |source|.{{GPUBufferCopyView/rowsPerImage}} must be a multiple of |blockHeight|. + - |copySize|.[=Extent3D/width=] must be a multiple of |blockWidth|. + - |copySize|.[=Extent3D/height=] must be a multiple of |blockHeight|. + - |source|.{{GPUBufferCopyView/offset}} must be a multiple of |blockSize|. + + For other members in |source|: + - If |copySize|.[=Extent3D/height=] is greater than 1: + - |source|.{{GPUBufferCopyView/bytesPerRow}} must be greater than or equal to the number of |bytesInACompleteRow|. + - If |copySize|.[=Extent3D/depth=] is greater than 1: + - |source|.{{GPUBufferCopyView/rowsPerImage}} must be greater than or equal to the number of |bytesInACompleteImage|. + +Issue(gpuweb/gpuweb#69): Define the copies with {{GPUTextureDimension/1d}} and +{{GPUTextureDimension/3d}} textures. + +Issue(gpuweb/gpuweb#537): Additional restrictions on rowsPerImage if needed. + +Issue(gpuweb/gpuweb#652): Define the copies with {{GPUTextureFormat/"depth24plus"}} and +{{GPUTextureFormat/"depth24plus-stencil8"}}. + +
+ ## Programmable Passes ## {#programmable-passes}