-
Notifications
You must be signed in to change notification settings - Fork 335
Add validation rules for copyBufferToTexture #648
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Thanks, it looks very good overall, I just wish the usage rules where grouped semantically, as right now it's difficult to make sure everything is handled. Maybe it could be:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! Just have a few notes
spec/index.bs
Outdated
- If |source|.{{GPUBufferCopyView/bytesPerRow}} is 0, the number of |bytes in a complete row| must be a multiple of 256. | ||
- |destination|.{{GPUTextureCopyView/mipLevel}} must be less than the {{GPUTexture/[[mipLevelCount]]}} of |destination|.{{GPUTextureCopyView/texture}}. | ||
- |destination|.{{GPUTextureCopyView/arrayLayer}} must be less than the {{GPUTexture/[[textureSize]]}}.{{GPUExtent3DDict/depth}} of |destination|.{{GPUTextureCopyView/texture}}. | ||
- {{GPUExtent3DDict/depth}} must be 1 when the {{GPUTexture/[[dimension]]}} of {{GPUTextureCopyView/texture}} is {{GPUTextureDimension/2d}}. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also, for GPUTextureDimension/1d
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually not true for 2d textures, because all 2d textures are semantically 2d texture arrays. Instead, this should just say the depth must be <= the texture's depth.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Metal only supports copying into one layer of a 2d texture:
https://developer.apple.com/documentation/metal/mtlblitcommandencoder/1400752-copyfrombuffer?language=objc
"when you copy to a 2D texture, depth must be 1."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we want to expose multi-layer copies, we can implement them as multiple copies when necessary
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"when you copy to a 2D texture, depth must be 1."
I'm pretty sure this is talking about 2D non-array textures specifically.
That documentation is kind of confusing though. On sourceBytesPerImage it says:
For 3D textures and 2D array textures, the stride in bytes between 2D images of the source buffer memory. The value must be a multiple of the destination texture's pixel size, in bytes.
which strongly implies that copies into multiple layers of a 2D array texture is allowed. But destinationSlice doesn't say anything about it. I think destinationSlice is actually destinationFirstSlice?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @JusSn @litherum, what do you think?
I also notice that in MoltenVK the multi-layer copy is implemented by an iteration over every layers in a for-loop.
spec/index.bs
Outdated
- If |source|.{{GPUBufferCopyView/bytesPerRow}} is 0, the number of |bytes in a complete row| must be a multiple of 256. | ||
- |destination|.{{GPUTextureCopyView/mipLevel}} must be less than the {{GPUTexture/[[mipLevelCount]]}} of |destination|.{{GPUTextureCopyView/texture}}. | ||
- |destination|.{{GPUTextureCopyView/arrayLayer}} must be less than the {{GPUTexture/[[textureSize]]}}.{{GPUExtent3DDict/depth}} of |destination|.{{GPUTextureCopyView/texture}}. | ||
- {{GPUExtent3DDict/depth}} must be 1 when the {{GPUTexture/[[dimension]]}} of {{GPUTextureCopyView/texture}} is {{GPUTextureDimension/2d}}. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually not true for 2d textures, because all 2d textures are semantically 2d texture arrays. Instead, this should just say the depth must be <= the texture's depth.
spec/index.bs
Outdated
- |copySize|.[=Extent3D/width=] cannot be 0. | ||
- |copySize|.[=Extent3D/height=] cannot be 0. | ||
- |copySize|.[=Extent3D/depth=] cannot be 0. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found on D3D12 it is not allowed to specify copySize.width, copySize.height or copySize.depth to 0 when I was writing SPEC for copy commands, so here I suggest we not allow copySize.width, copySize.height or copySize.depth be 0.
Here are the error message reported from D3D12 validation layer:
D3D12 ERROR: ID3D12CommandList::CopyTextureRegion: D3D12_SUBRESOURCE_FOOTPRINT::Width, D3D12_SUBRESOURCE_FOOTPRINT::Height, and D3D12_SUBRESOURCE_FOOTPRINT::Depth cannot be 0. The minimum value is 1. Width = 64, Height = 0, and Depth = 1. [ RESOURCE_MANIPULATION ERROR #854: COPYTEXTUREREGION_INVALIDDSTDIMENSIONS]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Imho empty copies should be allowed, because making them noops is as much work as validating them out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So you are suggesting that "it is no-op if any of the copySize.width, copySize.height or copySize.depth is 0"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but that can be non-normative ("Note: ...") because when we actually define the copies they'll probably be done as for-loops which describe that behavior.
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. | ||
- If the {{GPUTexture/[[dimension]]}} of |textureCopyView|.{{GPUTextureCopyView/texture}} is {{GPUTextureDimension/2d}}: | ||
- |textureCopyView|.{{GPUTextureCopyView/arrayLayer}} must be less than the {{GPUTexture/[[textureSize]]}}.[=Extent3D/depth=] of |textureCopyView|.{{GPUTextureCopyView/texture}}. | ||
- |textureCopyView|.{{GPUTextureCopyView/origin}}.{{GPUOrigin3DDict/x}} must be a multiple of |blockWidth|. | ||
- |textureCopyView|.{{GPUTextureCopyView/origin}}.{{GPUOrigin3DDict/y}} must be a multiple of |blockHeight|. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These rules are the same for both buffer-to-texture and texture-to-buffer copies so I decide to put it here.
nit: Please mark comment threads as "resolved" when you resolve them so they get minimized; you can do that instead of commenting "Done". :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for another huge review!! This is looking really good overall!
OK. There are totally 5 TODOs:
|
There was agreement in the F2F here (based on my recollection - the minutes don't seem to capture it) that rowsPerImage=0 would only be allowed for 2d copies (there's no "tightly packed" mode for it). I thought we also agreed there would be no "tightly packed" mode for bytesPerRow but maybe @kvark @JusSn could give explicit approval on that (and the other issues). Note that it would be a nonbreaking change to allow "0 = tightly packed" later on if we really find it's useful. |
Resolutions from the meeting:
bytesPerRow = 0 has no special meaning. Have a rule saying two rows of the copy may not overlap, making 0 invalid if height>1. rowsPerImage = 0 has no special meaning. Have a rule saying two images of the copy may not overlap, making 0 invalid if depth > 1.
Yes, but don't explicitly call it out (except maybe in non-normative text). Just don't disallow CopySize=0.
Yes.
Leave TODOs in the spec for now. |
Hi @kainino0x, I have updated all these changes in the latest commit. PTAL, thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
latest commit lgtm with nits, but I still have a bunch of open comments that I'd like to get resolved at some point.
I think we should merge this without those. I think I'll go ahead and take care of some syntax stuff right now.
Hi @kainino0x, I have updated this PR. PTAL, thanks! |
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we may need to put an Issue here to clarify what "contiguous" means.
I.e. if I select mipmaps 1-2 and array layers 1-2, is that sub-region contiguous?
Last commit LGTM. Jiawei, will you be able to take a followup to address the rest of the unresolved comments on this PR? |
@kainino0x @kvark @Kangz thanks for all your suggestions!
Yes I will. I plan to do further investigations after finishing another two PRs about the copy commmands (texture-to-buffer and texture-to-texture). |
* Add validation rules for copyBufferToTexture * Small fix * Address more reviewer's suggestions * Address more comments from the reviewers * Fix several typos
* Add validation rules for copyBufferToTexture * Small fix * Address more reviewer's suggestions * Address more comments from the reviewers * Fix several typos
@Jiawei-Shao I think the open issues on this PR are still open. Will you be able to take them? Also, I just noticed that the rendered indentation for "For other members in layout:" in the spec right now is broken. |
@kainino0x Yes I will. Here are the remaining two opens:
Also now we don't allow |
I'm mainly talking about the copyediting issues outstanding above: indentation, naming, incorrect usage of |
* Depth/stencil formats should be invalid for 3D textures * Address feedback from Kai: need to revise test name or description * Address feedback from Kai
Preview | Diff