Corentin Wallez | e1f0d4e | 2019-02-15 12:54:08 +0000 | [diff] [blame] | 1 | // Copyright 2019 The Dawn Authors |
| 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | |
| 15 | #include "dawn_native/CommandEncoder.h" |
| 16 | |
Corentin Wallez | f20f5b9 | 2019-02-20 11:46:16 +0000 | [diff] [blame] | 17 | #include "common/BitSetIterator.h" |
Tomek Ponitka | 7ce4924 | 2020-08-05 16:43:24 +0000 | [diff] [blame] | 18 | #include "common/Math.h" |
Corentin Wallez | f20f5b9 | 2019-02-20 11:46:16 +0000 | [diff] [blame] | 19 | #include "dawn_native/BindGroup.h" |
| 20 | #include "dawn_native/Buffer.h" |
Corentin Wallez | e1f0d4e | 2019-02-15 12:54:08 +0000 | [diff] [blame] | 21 | #include "dawn_native/CommandBuffer.h" |
Corentin Wallez | f20f5b9 | 2019-02-20 11:46:16 +0000 | [diff] [blame] | 22 | #include "dawn_native/CommandBufferStateTracker.h" |
Austin Eng | 3318caa | 2019-08-13 00:22:28 +0000 | [diff] [blame] | 23 | #include "dawn_native/CommandValidation.h" |
Corentin Wallez | f20f5b9 | 2019-02-20 11:46:16 +0000 | [diff] [blame] | 24 | #include "dawn_native/Commands.h" |
| 25 | #include "dawn_native/ComputePassEncoder.h" |
Corentin Wallez | e1f0d4e | 2019-02-15 12:54:08 +0000 | [diff] [blame] | 26 | #include "dawn_native/Device.h" |
Corentin Wallez | f20f5b9 | 2019-02-20 11:46:16 +0000 | [diff] [blame] | 27 | #include "dawn_native/ErrorData.h" |
Hao Li | 6f833b7 | 2021-01-14 03:26:08 +0000 | [diff] [blame] | 28 | #include "dawn_native/QueryHelper.h" |
Hao Li | 5191adc | 2020-07-01 10:48:16 +0000 | [diff] [blame] | 29 | #include "dawn_native/QuerySet.h" |
Hao Li | 6f833b7 | 2021-01-14 03:26:08 +0000 | [diff] [blame] | 30 | #include "dawn_native/Queue.h" |
Corentin Wallez | f20f5b9 | 2019-02-20 11:46:16 +0000 | [diff] [blame] | 31 | #include "dawn_native/RenderPassEncoder.h" |
| 32 | #include "dawn_native/RenderPipeline.h" |
Jiawei Shao | 51c347a | 2019-12-12 01:29:01 +0000 | [diff] [blame] | 33 | #include "dawn_native/ValidationUtils_autogen.h" |
Austin Eng | 73d5bb5 | 2019-10-28 23:15:40 +0000 | [diff] [blame] | 34 | #include "dawn_platform/DawnPlatform.h" |
Austin Eng | d4ce736 | 2019-08-13 19:00:34 +0000 | [diff] [blame] | 35 | #include "dawn_platform/tracing/TraceEvent.h" |
Corentin Wallez | f20f5b9 | 2019-02-20 11:46:16 +0000 | [diff] [blame] | 36 | |
Corentin Wallez | e51f8dd | 2020-02-18 02:44:05 +0000 | [diff] [blame] | 37 | #include <cmath> |
Corentin Wallez | f20f5b9 | 2019-02-20 11:46:16 +0000 | [diff] [blame] | 38 | #include <map> |
Corentin Wallez | e1f0d4e | 2019-02-15 12:54:08 +0000 | [diff] [blame] | 39 | |
| 40 | namespace dawn_native { |
| 41 | |
Corentin Wallez | f20f5b9 | 2019-02-20 11:46:16 +0000 | [diff] [blame] | 42 | namespace { |
| 43 | |
Brandon Jones | 55a3897 | 2021-06-28 18:38:24 +0000 | [diff] [blame] | 44 | MaybeError ValidateDeprecatedStoreOp(DeviceBase* device, wgpu::StoreOp value) { |
| 45 | if (value == wgpu::StoreOp::Clear) { |
| 46 | device->EmitDeprecationWarning( |
| 47 | "The 'clear' storeOp is deprecated. Use 'discard' instead."); |
| 48 | } |
| 49 | return ValidateStoreOp(value); |
| 50 | } |
| 51 | |
Corentin Wallez | ecf9347 | 2020-05-05 08:33:55 +0000 | [diff] [blame] | 52 | MaybeError ValidateB2BCopyAlignment(uint64_t dataSize, |
| 53 | uint64_t srcOffset, |
| 54 | uint64_t dstOffset) { |
Yan, Shaobo | 738567f | 2019-02-27 02:46:27 +0000 | [diff] [blame] | 55 | // Copy size must be a multiple of 4 bytes on macOS. |
| 56 | if (dataSize % 4 != 0) { |
| 57 | return DAWN_VALIDATION_ERROR("Copy size must be a multiple of 4 bytes"); |
| 58 | } |
| 59 | |
| 60 | // SourceOffset and destinationOffset must be multiples of 4 bytes on macOS. |
| 61 | if (srcOffset % 4 != 0 || dstOffset % 4 != 0) { |
| 62 | return DAWN_VALIDATION_ERROR( |
| 63 | "Source offset and destination offset must be multiples of 4 bytes"); |
| 64 | } |
| 65 | |
| 66 | return {}; |
| 67 | } |
| 68 | |
Austin Eng | f114a68 | 2020-09-01 18:40:18 +0000 | [diff] [blame] | 69 | MaybeError ValidateTextureSampleCountInBufferCopyCommands(const TextureBase* texture) { |
Jiawei Shao | 081d5c2 | 2019-03-04 12:01:59 +0000 | [diff] [blame] | 70 | if (texture->GetSampleCount() > 1) { |
Brandon Jones | d3d3aa0 | 2019-03-26 11:06:23 +0000 | [diff] [blame] | 71 | return DAWN_VALIDATION_ERROR( |
Austin Eng | f114a68 | 2020-09-01 18:40:18 +0000 | [diff] [blame] | 72 | "The sample count of textures must be 1 when copying between buffers and " |
| 73 | "textures"); |
Brandon Jones | d3d3aa0 | 2019-03-26 11:06:23 +0000 | [diff] [blame] | 74 | } |
| 75 | |
| 76 | return {}; |
| 77 | } |
| 78 | |
Kai Ninomiya | 54123a3 | 2020-10-27 19:30:57 +0000 | [diff] [blame] | 79 | MaybeError ValidateLinearTextureCopyOffset(const TextureDataLayout& layout, |
Zhaoming Jiang | 1af81e3 | 2021-06-24 05:38:00 +0000 | [diff] [blame] | 80 | const TexelBlockInfo& blockInfo, |
| 81 | const bool hasDepthOrStencil) { |
| 82 | if (hasDepthOrStencil) { |
| 83 | // For depth-stencil texture, buffer offset must be a multiple of 4. |
| 84 | if (layout.offset % 4 != 0) { |
| 85 | return DAWN_VALIDATION_ERROR( |
| 86 | "offset must be a multiple of 4 for depth/stencil texture."); |
| 87 | } |
| 88 | } else { |
| 89 | if (layout.offset % blockInfo.byteSize != 0) { |
| 90 | return DAWN_VALIDATION_ERROR( |
| 91 | "offset must be a multiple of the texel block byte size."); |
| 92 | } |
Austin Eng | 0d9fce1 | 2020-07-30 15:29:57 +0000 | [diff] [blame] | 93 | } |
Kai Ninomiya | 54123a3 | 2020-10-27 19:30:57 +0000 | [diff] [blame] | 94 | return {}; |
| 95 | } |
Austin Eng | 0d9fce1 | 2020-07-30 15:29:57 +0000 | [diff] [blame] | 96 | |
Corentin Wallez | 8091584 | 2021-03-04 18:13:45 +0000 | [diff] [blame] | 97 | MaybeError ValidateTextureDepthStencilToBufferCopyRestrictions( |
| 98 | const ImageCopyTexture& src) { |
Kai Ninomiya | 54123a3 | 2020-10-27 19:30:57 +0000 | [diff] [blame] | 99 | Aspect aspectUsed; |
Corentin Wallez | 8091584 | 2021-03-04 18:13:45 +0000 | [diff] [blame] | 100 | DAWN_TRY_ASSIGN(aspectUsed, SingleAspectUsedByImageCopyTexture(src)); |
Kai Ninomiya | 54123a3 | 2020-10-27 19:30:57 +0000 | [diff] [blame] | 101 | if (aspectUsed == Aspect::Depth) { |
| 102 | switch (src.texture->GetFormat().format) { |
Austin Eng | 0d9fce1 | 2020-07-30 15:29:57 +0000 | [diff] [blame] | 103 | case wgpu::TextureFormat::Depth24Plus: |
| 104 | case wgpu::TextureFormat::Depth24PlusStencil8: |
| 105 | return DAWN_VALIDATION_ERROR( |
| 106 | "The depth aspect of depth24plus texture cannot be selected in a " |
| 107 | "texture to buffer copy"); |
Austin Eng | 0d9fce1 | 2020-07-30 15:29:57 +0000 | [diff] [blame] | 108 | case wgpu::TextureFormat::Depth32Float: |
| 109 | break; |
Corentin Wallez | eec9edf | 2020-09-24 14:56:50 +0000 | [diff] [blame] | 110 | |
Austin Eng | 0d9fce1 | 2020-07-30 15:29:57 +0000 | [diff] [blame] | 111 | default: |
| 112 | UNREACHABLE(); |
Austin Eng | 0d9fce1 | 2020-07-30 15:29:57 +0000 | [diff] [blame] | 113 | } |
| 114 | } |
| 115 | |
| 116 | return {}; |
| 117 | } |
| 118 | |
Jiawei Shao | b2c5023 | 2019-02-27 09:21:56 +0000 | [diff] [blame] | 119 | MaybeError ValidateAttachmentArrayLayersAndLevelCount(const TextureViewBase* attachment) { |
| 120 | // Currently we do not support layered rendering. |
| 121 | if (attachment->GetLayerCount() > 1) { |
| 122 | return DAWN_VALIDATION_ERROR( |
| 123 | "The layer count of the texture view used as attachment cannot be greater than " |
| 124 | "1"); |
| 125 | } |
| 126 | |
| 127 | if (attachment->GetLevelCount() > 1) { |
| 128 | return DAWN_VALIDATION_ERROR( |
| 129 | "The mipmap level count of the texture view used as attachment cannot be " |
| 130 | "greater than 1"); |
| 131 | } |
| 132 | |
| 133 | return {}; |
| 134 | } |
| 135 | |
| 136 | MaybeError ValidateOrSetAttachmentSize(const TextureViewBase* attachment, |
| 137 | uint32_t* width, |
| 138 | uint32_t* height) { |
Stephen White | ed3a93f | 2020-10-02 16:15:40 +0000 | [diff] [blame] | 139 | const Extent3D& attachmentSize = |
| 140 | attachment->GetTexture()->GetMipLevelVirtualSize(attachment->GetBaseMipLevel()); |
Jiawei Shao | b2c5023 | 2019-02-27 09:21:56 +0000 | [diff] [blame] | 141 | |
| 142 | if (*width == 0) { |
| 143 | DAWN_ASSERT(*height == 0); |
Stephen White | ed3a93f | 2020-10-02 16:15:40 +0000 | [diff] [blame] | 144 | *width = attachmentSize.width; |
| 145 | *height = attachmentSize.height; |
Jiawei Shao | b2c5023 | 2019-02-27 09:21:56 +0000 | [diff] [blame] | 146 | DAWN_ASSERT(*width != 0 && *height != 0); |
Stephen White | ed3a93f | 2020-10-02 16:15:40 +0000 | [diff] [blame] | 147 | } else if (*width != attachmentSize.width || *height != attachmentSize.height) { |
Jiawei Shao | b2c5023 | 2019-02-27 09:21:56 +0000 | [diff] [blame] | 148 | return DAWN_VALIDATION_ERROR("Attachment size mismatch"); |
| 149 | } |
| 150 | |
| 151 | return {}; |
| 152 | } |
| 153 | |
Jiawei Shao | 1e1c13e | 2019-03-11 18:41:02 +0000 | [diff] [blame] | 154 | MaybeError ValidateOrSetColorAttachmentSampleCount(const TextureViewBase* colorAttachment, |
| 155 | uint32_t* sampleCount) { |
| 156 | if (*sampleCount == 0) { |
| 157 | *sampleCount = colorAttachment->GetTexture()->GetSampleCount(); |
| 158 | DAWN_ASSERT(*sampleCount != 0); |
| 159 | } else if (*sampleCount != colorAttachment->GetTexture()->GetSampleCount()) { |
| 160 | return DAWN_VALIDATION_ERROR("Color attachment sample counts mismatch"); |
| 161 | } |
| 162 | |
| 163 | return {}; |
| 164 | } |
| 165 | |
| 166 | MaybeError ValidateResolveTarget( |
| 167 | const DeviceBase* device, |
Corentin Wallez | a838c7d | 2019-09-20 22:59:47 +0000 | [diff] [blame] | 168 | const RenderPassColorAttachmentDescriptor& colorAttachment) { |
| 169 | if (colorAttachment.resolveTarget == nullptr) { |
Jiawei Shao | 1e1c13e | 2019-03-11 18:41:02 +0000 | [diff] [blame] | 170 | return {}; |
| 171 | } |
| 172 | |
Corentin Wallez | a838c7d | 2019-09-20 22:59:47 +0000 | [diff] [blame] | 173 | const TextureViewBase* resolveTarget = colorAttachment.resolveTarget; |
Brandon Jones | 5e6a092 | 2021-04-17 01:51:53 +0000 | [diff] [blame] | 174 | const TextureViewBase* attachment = |
| 175 | colorAttachment.view != nullptr ? colorAttachment.view : colorAttachment.attachment; |
Corentin Wallez | a838c7d | 2019-09-20 22:59:47 +0000 | [diff] [blame] | 176 | DAWN_TRY(device->ValidateObject(colorAttachment.resolveTarget)); |
Corentin Wallez | 72cd1a5 | 2021-01-22 11:31:08 +0000 | [diff] [blame] | 177 | DAWN_TRY(ValidateCanUseAs(colorAttachment.resolveTarget->GetTexture(), |
| 178 | wgpu::TextureUsage::RenderAttachment)); |
Jiawei Shao | 1e1c13e | 2019-03-11 18:41:02 +0000 | [diff] [blame] | 179 | |
Corentin Wallez | a838c7d | 2019-09-20 22:59:47 +0000 | [diff] [blame] | 180 | if (!attachment->GetTexture()->IsMultisampledTexture()) { |
Jiawei Shao | 1e1c13e | 2019-03-11 18:41:02 +0000 | [diff] [blame] | 181 | return DAWN_VALIDATION_ERROR( |
| 182 | "Cannot set resolve target when the sample count of the color attachment is 1"); |
| 183 | } |
| 184 | |
Corentin Wallez | a838c7d | 2019-09-20 22:59:47 +0000 | [diff] [blame] | 185 | if (resolveTarget->GetTexture()->IsMultisampledTexture()) { |
Jiawei Shao | 1e1c13e | 2019-03-11 18:41:02 +0000 | [diff] [blame] | 186 | return DAWN_VALIDATION_ERROR("Cannot use multisampled texture as resolve target"); |
| 187 | } |
| 188 | |
Corentin Wallez | a838c7d | 2019-09-20 22:59:47 +0000 | [diff] [blame] | 189 | if (resolveTarget->GetLayerCount() > 1) { |
Jiawei Shao | 1e1c13e | 2019-03-11 18:41:02 +0000 | [diff] [blame] | 190 | return DAWN_VALIDATION_ERROR( |
| 191 | "The array layer count of the resolve target must be 1"); |
| 192 | } |
| 193 | |
Corentin Wallez | a838c7d | 2019-09-20 22:59:47 +0000 | [diff] [blame] | 194 | if (resolveTarget->GetLevelCount() > 1) { |
Jiawei Shao | 1e1c13e | 2019-03-11 18:41:02 +0000 | [diff] [blame] | 195 | return DAWN_VALIDATION_ERROR("The mip level count of the resolve target must be 1"); |
| 196 | } |
| 197 | |
Yunchao He | 4043ee9 | 2021-04-30 17:51:58 +0000 | [diff] [blame] | 198 | const Extent3D& colorTextureSize = |
| 199 | attachment->GetTexture()->GetMipLevelVirtualSize(attachment->GetBaseMipLevel()); |
| 200 | const Extent3D& resolveTextureSize = |
| 201 | resolveTarget->GetTexture()->GetMipLevelVirtualSize( |
| 202 | resolveTarget->GetBaseMipLevel()); |
| 203 | if (colorTextureSize.width != resolveTextureSize.width || |
| 204 | colorTextureSize.height != resolveTextureSize.height) { |
Jiawei Shao | 1e1c13e | 2019-03-11 18:41:02 +0000 | [diff] [blame] | 205 | return DAWN_VALIDATION_ERROR( |
| 206 | "The size of the resolve target must be the same as the color attachment"); |
| 207 | } |
| 208 | |
Corentin Wallez | 1f6c8c4 | 2019-10-23 11:57:41 +0000 | [diff] [blame] | 209 | wgpu::TextureFormat resolveTargetFormat = resolveTarget->GetFormat().format; |
Corentin Wallez | a838c7d | 2019-09-20 22:59:47 +0000 | [diff] [blame] | 210 | if (resolveTargetFormat != attachment->GetFormat().format) { |
Jiawei Shao | 1e1c13e | 2019-03-11 18:41:02 +0000 | [diff] [blame] | 211 | return DAWN_VALIDATION_ERROR( |
| 212 | "The format of the resolve target must be the same as the color attachment"); |
| 213 | } |
| 214 | |
| 215 | return {}; |
| 216 | } |
| 217 | |
Jiawei Shao | b2c5023 | 2019-02-27 09:21:56 +0000 | [diff] [blame] | 218 | MaybeError ValidateRenderPassColorAttachment( |
Brandon Jones | 5e6a092 | 2021-04-17 01:51:53 +0000 | [diff] [blame] | 219 | DeviceBase* device, |
Corentin Wallez | a838c7d | 2019-09-20 22:59:47 +0000 | [diff] [blame] | 220 | const RenderPassColorAttachmentDescriptor& colorAttachment, |
Jiawei Shao | b2c5023 | 2019-02-27 09:21:56 +0000 | [diff] [blame] | 221 | uint32_t* width, |
Jiawei Shao | 1e1c13e | 2019-03-11 18:41:02 +0000 | [diff] [blame] | 222 | uint32_t* height, |
| 223 | uint32_t* sampleCount) { |
Brandon Jones | 5e6a092 | 2021-04-17 01:51:53 +0000 | [diff] [blame] | 224 | TextureViewBase* attachment; |
| 225 | if (colorAttachment.view != nullptr) { |
| 226 | if (colorAttachment.attachment != nullptr) { |
| 227 | return DAWN_VALIDATION_ERROR( |
| 228 | "Cannot specify both a attachment and view. attachment is deprecated, " |
| 229 | "favor view instead."); |
| 230 | } |
| 231 | attachment = colorAttachment.view; |
| 232 | } else if (colorAttachment.attachment != nullptr) { |
| 233 | device->EmitDeprecationWarning( |
| 234 | "RenderPassColorAttachmentDescriptor.attachment has been deprecated. Use " |
| 235 | "RenderPassColorAttachmentDescriptor.view instead."); |
| 236 | attachment = colorAttachment.attachment; |
| 237 | } else { |
| 238 | return DAWN_VALIDATION_ERROR( |
| 239 | "Must specify a view for RenderPassColorAttachmentDescriptor"); |
| 240 | } |
Jiawei Shao | b2c5023 | 2019-02-27 09:21:56 +0000 | [diff] [blame] | 241 | |
Brandon Jones | 5e6a092 | 2021-04-17 01:51:53 +0000 | [diff] [blame] | 242 | DAWN_TRY(device->ValidateObject(attachment)); |
| 243 | DAWN_TRY( |
| 244 | ValidateCanUseAs(attachment->GetTexture(), wgpu::TextureUsage::RenderAttachment)); |
| 245 | |
Corentin Wallez | 49c30a7 | 2020-10-15 09:15:53 +0000 | [diff] [blame] | 246 | if (!(attachment->GetAspects() & Aspect::Color) || |
| 247 | !attachment->GetFormat().isRenderable) { |
Jiawei Shao | b2c5023 | 2019-02-27 09:21:56 +0000 | [diff] [blame] | 248 | return DAWN_VALIDATION_ERROR( |
| 249 | "The format of the texture view used as color attachment is not color " |
| 250 | "renderable"); |
| 251 | } |
| 252 | |
Jiawei Shao | 51c347a | 2019-12-12 01:29:01 +0000 | [diff] [blame] | 253 | DAWN_TRY(ValidateLoadOp(colorAttachment.loadOp)); |
Brandon Jones | 55a3897 | 2021-06-28 18:38:24 +0000 | [diff] [blame] | 254 | DAWN_TRY(ValidateDeprecatedStoreOp(device, colorAttachment.storeOp)); |
Jiawei Shao | 51c347a | 2019-12-12 01:29:01 +0000 | [diff] [blame] | 255 | |
| 256 | if (colorAttachment.loadOp == wgpu::LoadOp::Clear) { |
| 257 | if (std::isnan(colorAttachment.clearColor.r) || |
| 258 | std::isnan(colorAttachment.clearColor.g) || |
| 259 | std::isnan(colorAttachment.clearColor.b) || |
| 260 | std::isnan(colorAttachment.clearColor.a)) { |
| 261 | return DAWN_VALIDATION_ERROR("Color clear value cannot contain NaN"); |
| 262 | } |
| 263 | } |
| 264 | |
Jiawei Shao | 1e1c13e | 2019-03-11 18:41:02 +0000 | [diff] [blame] | 265 | DAWN_TRY(ValidateOrSetColorAttachmentSampleCount(attachment, sampleCount)); |
| 266 | |
| 267 | DAWN_TRY(ValidateResolveTarget(device, colorAttachment)); |
| 268 | |
Jiawei Shao | b2c5023 | 2019-02-27 09:21:56 +0000 | [diff] [blame] | 269 | DAWN_TRY(ValidateAttachmentArrayLayersAndLevelCount(attachment)); |
| 270 | DAWN_TRY(ValidateOrSetAttachmentSize(attachment, width, height)); |
| 271 | |
| 272 | return {}; |
| 273 | } |
| 274 | |
| 275 | MaybeError ValidateRenderPassDepthStencilAttachment( |
Brandon Jones | 5e6a092 | 2021-04-17 01:51:53 +0000 | [diff] [blame] | 276 | DeviceBase* device, |
Jiawei Shao | b2c5023 | 2019-02-27 09:21:56 +0000 | [diff] [blame] | 277 | const RenderPassDepthStencilAttachmentDescriptor* depthStencilAttachment, |
| 278 | uint32_t* width, |
Jiawei Shao | 9313117 | 2019-03-15 05:16:41 +0000 | [diff] [blame] | 279 | uint32_t* height, |
| 280 | uint32_t* sampleCount) { |
Jiawei Shao | b2c5023 | 2019-02-27 09:21:56 +0000 | [diff] [blame] | 281 | DAWN_ASSERT(depthStencilAttachment != nullptr); |
| 282 | |
Brandon Jones | 5e6a092 | 2021-04-17 01:51:53 +0000 | [diff] [blame] | 283 | TextureViewBase* attachment; |
| 284 | if (depthStencilAttachment->view != nullptr) { |
| 285 | if (depthStencilAttachment->attachment != nullptr) { |
| 286 | return DAWN_VALIDATION_ERROR( |
| 287 | "Cannot specify both a attachment and view. attachment is deprecated, " |
| 288 | "favor view instead."); |
| 289 | } |
| 290 | attachment = depthStencilAttachment->view; |
| 291 | } else if (depthStencilAttachment->attachment != nullptr) { |
| 292 | device->EmitDeprecationWarning( |
| 293 | "RenderPassDepthStencilAttachmentDescriptor.attachment has been deprecated. " |
| 294 | "Use RenderPassDepthStencilAttachmentDescriptor.view instead."); |
| 295 | attachment = depthStencilAttachment->attachment; |
| 296 | } else { |
| 297 | return DAWN_VALIDATION_ERROR( |
| 298 | "Must specify a view for RenderPassDepthStencilAttachmentDescriptor"); |
| 299 | } |
Jiawei Shao | b2c5023 | 2019-02-27 09:21:56 +0000 | [diff] [blame] | 300 | |
Brandon Jones | 5e6a092 | 2021-04-17 01:51:53 +0000 | [diff] [blame] | 301 | DAWN_TRY(device->ValidateObject(attachment)); |
| 302 | DAWN_TRY( |
| 303 | ValidateCanUseAs(attachment->GetTexture(), wgpu::TextureUsage::RenderAttachment)); |
| 304 | |
Corentin Wallez | 5a53eb3 | 2021-06-11 14:25:29 +0000 | [diff] [blame] | 305 | const Format& format = attachment->GetFormat(); |
| 306 | if (!format.HasDepthOrStencil()) { |
Jiawei Shao | b2c5023 | 2019-02-27 09:21:56 +0000 | [diff] [blame] | 307 | return DAWN_VALIDATION_ERROR( |
| 308 | "The format of the texture view used as depth stencil attachment is not a " |
| 309 | "depth stencil format"); |
| 310 | } |
Corentin Wallez | 5a53eb3 | 2021-06-11 14:25:29 +0000 | [diff] [blame] | 311 | if (!format.isRenderable) { |
| 312 | return DAWN_VALIDATION_ERROR( |
| 313 | "The format of the texture view used as depth stencil attachment is not " |
| 314 | "renderable"); |
| 315 | } |
| 316 | if (attachment->GetAspects() != format.aspects) { |
| 317 | // TODO(https://crbug.com/dawn/812): Investigate if this limitation should be added |
| 318 | // to the WebGPU spec of lifted from Dawn. |
| 319 | return DAWN_VALIDATION_ERROR( |
| 320 | "The texture view used as depth stencil view must encompass all aspects"); |
| 321 | } |
Jiawei Shao | b2c5023 | 2019-02-27 09:21:56 +0000 | [diff] [blame] | 322 | |
Jiawei Shao | 51c347a | 2019-12-12 01:29:01 +0000 | [diff] [blame] | 323 | DAWN_TRY(ValidateLoadOp(depthStencilAttachment->depthLoadOp)); |
| 324 | DAWN_TRY(ValidateLoadOp(depthStencilAttachment->stencilLoadOp)); |
Brandon Jones | 55a3897 | 2021-06-28 18:38:24 +0000 | [diff] [blame] | 325 | DAWN_TRY(ValidateDeprecatedStoreOp(device, depthStencilAttachment->depthStoreOp)); |
| 326 | DAWN_TRY(ValidateDeprecatedStoreOp(device, depthStencilAttachment->stencilStoreOp)); |
Jiawei Shao | 51c347a | 2019-12-12 01:29:01 +0000 | [diff] [blame] | 327 | |
Corentin Wallez | 49c30a7 | 2020-10-15 09:15:53 +0000 | [diff] [blame] | 328 | if (attachment->GetAspects() == (Aspect::Depth | Aspect::Stencil) && |
Brandon Jones | 7695afc | 2020-07-10 23:13:58 +0000 | [diff] [blame] | 329 | depthStencilAttachment->depthReadOnly != depthStencilAttachment->stencilReadOnly) { |
| 330 | return DAWN_VALIDATION_ERROR( |
| 331 | "depthReadOnly and stencilReadOnly must be the same when texture aspect is " |
| 332 | "'all'"); |
| 333 | } |
| 334 | |
| 335 | if (depthStencilAttachment->depthReadOnly && |
| 336 | (depthStencilAttachment->depthLoadOp != wgpu::LoadOp::Load || |
| 337 | depthStencilAttachment->depthStoreOp != wgpu::StoreOp::Store)) { |
| 338 | return DAWN_VALIDATION_ERROR( |
| 339 | "depthLoadOp must be load and depthStoreOp must be store when depthReadOnly " |
| 340 | "is true."); |
| 341 | } |
| 342 | |
| 343 | if (depthStencilAttachment->stencilReadOnly && |
| 344 | (depthStencilAttachment->stencilLoadOp != wgpu::LoadOp::Load || |
| 345 | depthStencilAttachment->stencilStoreOp != wgpu::StoreOp::Store)) { |
| 346 | return DAWN_VALIDATION_ERROR( |
| 347 | "stencilLoadOp must be load and stencilStoreOp must be store when " |
| 348 | "stencilReadOnly " |
| 349 | "is true."); |
| 350 | } |
| 351 | |
Jiawei Shao | 51c347a | 2019-12-12 01:29:01 +0000 | [diff] [blame] | 352 | if (depthStencilAttachment->depthLoadOp == wgpu::LoadOp::Clear && |
| 353 | std::isnan(depthStencilAttachment->clearDepth)) { |
| 354 | return DAWN_VALIDATION_ERROR("Depth clear value cannot be NaN"); |
| 355 | } |
| 356 | |
Jiawei Shao | 9313117 | 2019-03-15 05:16:41 +0000 | [diff] [blame] | 357 | // *sampleCount == 0 must only happen when there is no color attachment. In that case we |
| 358 | // do not need to validate the sample count of the depth stencil attachment. |
Jiawei Shao | 54e4d47 | 2019-03-19 01:12:01 +0000 | [diff] [blame] | 359 | const uint32_t depthStencilSampleCount = attachment->GetTexture()->GetSampleCount(); |
| 360 | if (*sampleCount != 0) { |
| 361 | if (depthStencilSampleCount != *sampleCount) { |
| 362 | return DAWN_VALIDATION_ERROR("Depth stencil attachment sample counts mismatch"); |
| 363 | } |
| 364 | } else { |
| 365 | *sampleCount = depthStencilSampleCount; |
Jiawei Shao | 9313117 | 2019-03-15 05:16:41 +0000 | [diff] [blame] | 366 | } |
| 367 | |
Jiawei Shao | b2c5023 | 2019-02-27 09:21:56 +0000 | [diff] [blame] | 368 | DAWN_TRY(ValidateAttachmentArrayLayersAndLevelCount(attachment)); |
| 369 | DAWN_TRY(ValidateOrSetAttachmentSize(attachment, width, height)); |
| 370 | |
| 371 | return {}; |
| 372 | } |
| 373 | |
Brandon Jones | 5e6a092 | 2021-04-17 01:51:53 +0000 | [diff] [blame] | 374 | MaybeError ValidateRenderPassDescriptor(DeviceBase* device, |
Corentin Wallez | 4b90c47 | 2019-07-10 20:43:13 +0000 | [diff] [blame] | 375 | const RenderPassDescriptor* descriptor, |
Jiawei Shao | 54e4d47 | 2019-03-19 01:12:01 +0000 | [diff] [blame] | 376 | uint32_t* width, |
| 377 | uint32_t* height, |
| 378 | uint32_t* sampleCount) { |
Corentin Wallez | 4b90c47 | 2019-07-10 20:43:13 +0000 | [diff] [blame] | 379 | if (descriptor->colorAttachmentCount > kMaxColorAttachments) { |
Jiawei Shao | b2c5023 | 2019-02-27 09:21:56 +0000 | [diff] [blame] | 380 | return DAWN_VALIDATION_ERROR("Setting color attachments out of bounds"); |
| 381 | } |
| 382 | |
Corentin Wallez | 4b90c47 | 2019-07-10 20:43:13 +0000 | [diff] [blame] | 383 | for (uint32_t i = 0; i < descriptor->colorAttachmentCount; ++i) { |
| 384 | DAWN_TRY(ValidateRenderPassColorAttachment(device, descriptor->colorAttachments[i], |
Jiawei Shao | 54e4d47 | 2019-03-19 01:12:01 +0000 | [diff] [blame] | 385 | width, height, sampleCount)); |
Jiawei Shao | b2c5023 | 2019-02-27 09:21:56 +0000 | [diff] [blame] | 386 | } |
| 387 | |
Corentin Wallez | 4b90c47 | 2019-07-10 20:43:13 +0000 | [diff] [blame] | 388 | if (descriptor->depthStencilAttachment != nullptr) { |
Jiawei Shao | b2c5023 | 2019-02-27 09:21:56 +0000 | [diff] [blame] | 389 | DAWN_TRY(ValidateRenderPassDepthStencilAttachment( |
Corentin Wallez | 4b90c47 | 2019-07-10 20:43:13 +0000 | [diff] [blame] | 390 | device, descriptor->depthStencilAttachment, width, height, sampleCount)); |
Jiawei Shao | b2c5023 | 2019-02-27 09:21:56 +0000 | [diff] [blame] | 391 | } |
| 392 | |
Kai Ninomiya | 53405b5 | 2020-07-11 03:15:16 +0000 | [diff] [blame] | 393 | if (descriptor->occlusionQuerySet != nullptr) { |
Hao Li | 01e4450 | 2020-11-18 09:47:52 +0000 | [diff] [blame] | 394 | DAWN_TRY(device->ValidateObject(descriptor->occlusionQuerySet)); |
| 395 | |
Hao Li | 01e4450 | 2020-11-18 09:47:52 +0000 | [diff] [blame] | 396 | if (descriptor->occlusionQuerySet->GetQueryType() != wgpu::QueryType::Occlusion) { |
| 397 | return DAWN_VALIDATION_ERROR("The type of query set must be Occlusion"); |
| 398 | } |
Kai Ninomiya | 53405b5 | 2020-07-11 03:15:16 +0000 | [diff] [blame] | 399 | } |
| 400 | |
Corentin Wallez | 4b90c47 | 2019-07-10 20:43:13 +0000 | [diff] [blame] | 401 | if (descriptor->colorAttachmentCount == 0 && |
| 402 | descriptor->depthStencilAttachment == nullptr) { |
Jiawei Shao | b2c5023 | 2019-02-27 09:21:56 +0000 | [diff] [blame] | 403 | return DAWN_VALIDATION_ERROR("Cannot use render pass with no attachments."); |
| 404 | } |
| 405 | |
| 406 | return {}; |
| 407 | } |
| 408 | |
Corentin Wallez | 4b90c47 | 2019-07-10 20:43:13 +0000 | [diff] [blame] | 409 | MaybeError ValidateComputePassDescriptor(const DeviceBase* device, |
| 410 | const ComputePassDescriptor* descriptor) { |
| 411 | return {}; |
| 412 | } |
| 413 | |
Hao Li | 5c89c8d | 2020-07-17 09:02:46 +0000 | [diff] [blame] | 414 | MaybeError ValidateQuerySetResolve(const QuerySetBase* querySet, |
| 415 | uint32_t firstQuery, |
| 416 | uint32_t queryCount, |
| 417 | const BufferBase* destination, |
| 418 | uint64_t destinationOffset) { |
| 419 | if (firstQuery >= querySet->GetQueryCount()) { |
| 420 | return DAWN_VALIDATION_ERROR("Query index out of bounds"); |
| 421 | } |
| 422 | |
| 423 | if (queryCount > querySet->GetQueryCount() - firstQuery) { |
| 424 | return DAWN_VALIDATION_ERROR( |
| 425 | "The sum of firstQuery and queryCount exceeds the number of queries in query " |
| 426 | "set"); |
| 427 | } |
| 428 | |
Hao Li | 5c89c8d | 2020-07-17 09:02:46 +0000 | [diff] [blame] | 429 | // The destinationOffset must be a multiple of 8 bytes on D3D12 and Vulkan |
| 430 | if (destinationOffset % 8 != 0) { |
| 431 | return DAWN_VALIDATION_ERROR( |
| 432 | "The alignment offset into the destination buffer must be a multiple of 8 " |
| 433 | "bytes"); |
| 434 | } |
| 435 | |
| 436 | uint64_t bufferSize = destination->GetSize(); |
| 437 | // The destination buffer must have enough storage, from destination offset, to contain |
| 438 | // the result of resolved queries |
| 439 | bool fitsInBuffer = destinationOffset <= bufferSize && |
| 440 | (static_cast<uint64_t>(queryCount) * sizeof(uint64_t) <= |
| 441 | (bufferSize - destinationOffset)); |
| 442 | if (!fitsInBuffer) { |
| 443 | return DAWN_VALIDATION_ERROR("The resolved query data would overflow the buffer"); |
| 444 | } |
| 445 | |
| 446 | return {}; |
| 447 | } |
| 448 | |
Corentin Wallez | 79c9d12 | 2021-03-31 11:24:42 +0000 | [diff] [blame] | 449 | MaybeError EncodeTimestampsToNanosecondsConversion(CommandEncoder* encoder, |
| 450 | QuerySetBase* querySet, |
Hao Li | 880a3d6 | 2021-05-18 01:13:08 +0000 | [diff] [blame] | 451 | uint32_t firstQuery, |
Corentin Wallez | 79c9d12 | 2021-03-31 11:24:42 +0000 | [diff] [blame] | 452 | uint32_t queryCount, |
| 453 | BufferBase* destination, |
| 454 | uint64_t destinationOffset) { |
Hao Li | 6f833b7 | 2021-01-14 03:26:08 +0000 | [diff] [blame] | 455 | DeviceBase* device = encoder->GetDevice(); |
| 456 | |
Hao Li | e0a5887 | 2021-02-10 14:01:36 +0000 | [diff] [blame] | 457 | // The availability got from query set is a reference to vector<bool>, need to covert |
| 458 | // bool to uint32_t due to a user input in pipeline must not contain a bool type in |
| 459 | // WGSL. |
| 460 | std::vector<uint32_t> availability{querySet->GetQueryAvailability().begin(), |
| 461 | querySet->GetQueryAvailability().end()}; |
Hao Li | 6f833b7 | 2021-01-14 03:26:08 +0000 | [diff] [blame] | 462 | |
| 463 | // Timestamp availability storage buffer |
| 464 | BufferDescriptor availabilityDesc = {}; |
| 465 | availabilityDesc.usage = wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopyDst; |
| 466 | availabilityDesc.size = querySet->GetQueryCount() * sizeof(uint32_t); |
Corentin Wallez | 0af4a83 | 2021-04-19 08:52:35 +0000 | [diff] [blame] | 467 | Ref<BufferBase> availabilityBuffer; |
| 468 | DAWN_TRY_ASSIGN(availabilityBuffer, device->CreateBuffer(&availabilityDesc)); |
| 469 | |
Corentin Wallez | 79c9d12 | 2021-03-31 11:24:42 +0000 | [diff] [blame] | 470 | DAWN_TRY(device->GetQueue()->WriteBuffer(availabilityBuffer.Get(), 0, |
| 471 | availability.data(), |
| 472 | availability.size() * sizeof(uint32_t))); |
Hao Li | 6f833b7 | 2021-01-14 03:26:08 +0000 | [diff] [blame] | 473 | |
| 474 | // Timestamp params uniform buffer |
Hao Li | 880a3d6 | 2021-05-18 01:13:08 +0000 | [diff] [blame] | 475 | TimestampParams params = {firstQuery, queryCount, |
| 476 | static_cast<uint32_t>(destinationOffset), |
Hao Li | 6f833b7 | 2021-01-14 03:26:08 +0000 | [diff] [blame] | 477 | device->GetTimestampPeriodInNS()}; |
Corentin Wallez | 0af4a83 | 2021-04-19 08:52:35 +0000 | [diff] [blame] | 478 | |
Hao Li | 6f833b7 | 2021-01-14 03:26:08 +0000 | [diff] [blame] | 479 | BufferDescriptor parmsDesc = {}; |
| 480 | parmsDesc.usage = wgpu::BufferUsage::Uniform | wgpu::BufferUsage::CopyDst; |
| 481 | parmsDesc.size = sizeof(params); |
Corentin Wallez | 0af4a83 | 2021-04-19 08:52:35 +0000 | [diff] [blame] | 482 | Ref<BufferBase> paramsBuffer; |
| 483 | DAWN_TRY_ASSIGN(paramsBuffer, device->CreateBuffer(&parmsDesc)); |
| 484 | |
Corentin Wallez | 79c9d12 | 2021-03-31 11:24:42 +0000 | [diff] [blame] | 485 | DAWN_TRY( |
| 486 | device->GetQueue()->WriteBuffer(paramsBuffer.Get(), 0, ¶ms, sizeof(params))); |
Hao Li | 6f833b7 | 2021-01-14 03:26:08 +0000 | [diff] [blame] | 487 | |
Corentin Wallez | 0af4a83 | 2021-04-19 08:52:35 +0000 | [diff] [blame] | 488 | return EncodeConvertTimestampsToNanoseconds( |
| 489 | encoder, destination, availabilityBuffer.Get(), paramsBuffer.Get()); |
Hao Li | 6f833b7 | 2021-01-14 03:26:08 +0000 | [diff] [blame] | 490 | } |
| 491 | |
Corentin Wallez | f20f5b9 | 2019-02-20 11:46:16 +0000 | [diff] [blame] | 492 | } // namespace |
| 493 | |
Corentin Wallez | 321c122 | 2019-11-13 17:00:37 +0000 | [diff] [blame] | 494 | CommandEncoder::CommandEncoder(DeviceBase* device, const CommandEncoderDescriptor*) |
Austin Eng | fde9490 | 2019-07-24 18:15:24 +0000 | [diff] [blame] | 495 | : ObjectBase(device), mEncodingContext(device, this) { |
Corentin Wallez | f20f5b9 | 2019-02-20 11:46:16 +0000 | [diff] [blame] | 496 | } |
| 497 | |
Corentin Wallez | 321c122 | 2019-11-13 17:00:37 +0000 | [diff] [blame] | 498 | CommandBufferResourceUsage CommandEncoder::AcquireResourceUsages() { |
Corentin Wallez | 2dd2d67 | 2021-05-05 15:41:13 +0000 | [diff] [blame] | 499 | return CommandBufferResourceUsage{ |
| 500 | mEncodingContext.AcquireRenderPassUsages(), mEncodingContext.AcquireComputePassUsages(), |
| 501 | std::move(mTopLevelBuffers), std::move(mTopLevelTextures), std::move(mUsedQuerySets)}; |
Corentin Wallez | f20f5b9 | 2019-02-20 11:46:16 +0000 | [diff] [blame] | 502 | } |
| 503 | |
Corentin Wallez | 321c122 | 2019-11-13 17:00:37 +0000 | [diff] [blame] | 504 | CommandIterator CommandEncoder::AcquireCommands() { |
Austin Eng | fde9490 | 2019-07-24 18:15:24 +0000 | [diff] [blame] | 505 | return mEncodingContext.AcquireCommands(); |
Corentin Wallez | f20f5b9 | 2019-02-20 11:46:16 +0000 | [diff] [blame] | 506 | } |
| 507 | |
Hao Li | 5191adc | 2020-07-01 10:48:16 +0000 | [diff] [blame] | 508 | void CommandEncoder::TrackUsedQuerySet(QuerySetBase* querySet) { |
| 509 | mUsedQuerySets.insert(querySet); |
| 510 | } |
| 511 | |
Hao Li | 575729e | 2020-11-16 02:24:06 +0000 | [diff] [blame] | 512 | void CommandEncoder::TrackQueryAvailability(QuerySetBase* querySet, uint32_t queryIndex) { |
| 513 | DAWN_ASSERT(querySet != nullptr); |
| 514 | |
| 515 | if (GetDevice()->IsValidationEnabled()) { |
| 516 | TrackUsedQuerySet(querySet); |
Hao Li | e2cbcc9 | 2020-10-21 08:38:31 +0000 | [diff] [blame] | 517 | } |
Hao Li | 575729e | 2020-11-16 02:24:06 +0000 | [diff] [blame] | 518 | |
Hao Li | e0a5887 | 2021-02-10 14:01:36 +0000 | [diff] [blame] | 519 | // Set the query at queryIndex to available for resolving in query set. |
Hao Li | d75f7c0 | 2021-04-07 05:39:21 +0000 | [diff] [blame] | 520 | querySet->SetQueryAvailability(queryIndex, true); |
Hao Li | e2cbcc9 | 2020-10-21 08:38:31 +0000 | [diff] [blame] | 521 | } |
| 522 | |
Corentin Wallez | f20f5b9 | 2019-02-20 11:46:16 +0000 | [diff] [blame] | 523 | // Implementation of the API's command recording methods |
| 524 | |
Corentin Wallez | 2ce4b90 | 2021-03-29 14:02:05 +0000 | [diff] [blame] | 525 | ComputePassEncoder* CommandEncoder::APIBeginComputePass( |
| 526 | const ComputePassDescriptor* descriptor) { |
Jiawei Shao | b47470d | 2019-03-05 01:02:47 +0000 | [diff] [blame] | 527 | DeviceBase* device = GetDevice(); |
Austin Eng | fde9490 | 2019-07-24 18:15:24 +0000 | [diff] [blame] | 528 | |
| 529 | bool success = |
| 530 | mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { |
| 531 | DAWN_TRY(ValidateComputePassDescriptor(device, descriptor)); |
| 532 | |
| 533 | allocator->Allocate<BeginComputePassCmd>(Command::BeginComputePass); |
| 534 | |
| 535 | return {}; |
| 536 | }); |
| 537 | |
| 538 | if (success) { |
Corentin Wallez | 321c122 | 2019-11-13 17:00:37 +0000 | [diff] [blame] | 539 | ComputePassEncoder* passEncoder = |
| 540 | new ComputePassEncoder(device, this, &mEncodingContext); |
Austin Eng | fde9490 | 2019-07-24 18:15:24 +0000 | [diff] [blame] | 541 | mEncodingContext.EnterPass(passEncoder); |
| 542 | return passEncoder; |
Corentin Wallez | f20f5b9 | 2019-02-20 11:46:16 +0000 | [diff] [blame] | 543 | } |
| 544 | |
Corentin Wallez | 321c122 | 2019-11-13 17:00:37 +0000 | [diff] [blame] | 545 | return ComputePassEncoder::MakeError(device, this, &mEncodingContext); |
Corentin Wallez | e1f0d4e | 2019-02-15 12:54:08 +0000 | [diff] [blame] | 546 | } |
| 547 | |
Corentin Wallez | 2ce4b90 | 2021-03-29 14:02:05 +0000 | [diff] [blame] | 548 | RenderPassEncoder* CommandEncoder::APIBeginRenderPass(const RenderPassDescriptor* descriptor) { |
Jiawei Shao | b2c5023 | 2019-02-27 09:21:56 +0000 | [diff] [blame] | 549 | DeviceBase* device = GetDevice(); |
| 550 | |
Corentin Wallez | ec7ea6a | 2021-05-05 19:55:23 +0000 | [diff] [blame] | 551 | RenderPassResourceUsageTracker usageTracker; |
Corentin Wallez | 6c3da3d | 2020-10-11 18:39:32 +0000 | [diff] [blame] | 552 | |
| 553 | uint32_t width = 0; |
| 554 | uint32_t height = 0; |
Corentin Wallez | 95ff834 | 2021-01-27 17:20:16 +0000 | [diff] [blame] | 555 | Ref<AttachmentState> attachmentState; |
Austin Eng | fde9490 | 2019-07-24 18:15:24 +0000 | [diff] [blame] | 556 | bool success = |
| 557 | mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { |
Austin Eng | fde9490 | 2019-07-24 18:15:24 +0000 | [diff] [blame] | 558 | uint32_t sampleCount = 0; |
| 559 | |
| 560 | DAWN_TRY(ValidateRenderPassDescriptor(device, descriptor, &width, &height, |
| 561 | &sampleCount)); |
| 562 | |
| 563 | ASSERT(width > 0 && height > 0 && sampleCount > 0); |
| 564 | |
| 565 | BeginRenderPassCmd* cmd = |
| 566 | allocator->Allocate<BeginRenderPassCmd>(Command::BeginRenderPass); |
| 567 | |
Austin Eng | b98f0fa | 2019-07-26 19:08:18 +0000 | [diff] [blame] | 568 | cmd->attachmentState = device->GetOrCreateAttachmentState(descriptor); |
Corentin Wallez | 95ff834 | 2021-01-27 17:20:16 +0000 | [diff] [blame] | 569 | attachmentState = cmd->attachmentState; |
Austin Eng | b98f0fa | 2019-07-26 19:08:18 +0000 | [diff] [blame] | 570 | |
Austin Eng | 7b7e098 | 2020-09-09 00:08:38 +0000 | [diff] [blame] | 571 | for (ColorAttachmentIndex index : |
| 572 | IterateBitSet(cmd->attachmentState->GetColorAttachmentsMask())) { |
| 573 | uint8_t i = static_cast<uint8_t>(index); |
Brandon Jones | 5e6a092 | 2021-04-17 01:51:53 +0000 | [diff] [blame] | 574 | TextureViewBase* view = descriptor->colorAttachments[i].view; |
| 575 | if (view == nullptr) { |
| 576 | view = descriptor->colorAttachments[i].attachment; |
| 577 | } |
Austin Eng | 4b0b7a5 | 2019-11-21 22:09:41 +0000 | [diff] [blame] | 578 | TextureViewBase* resolveTarget = descriptor->colorAttachments[i].resolveTarget; |
| 579 | |
Austin Eng | 7b7e098 | 2020-09-09 00:08:38 +0000 | [diff] [blame] | 580 | cmd->colorAttachments[index].view = view; |
| 581 | cmd->colorAttachments[index].resolveTarget = resolveTarget; |
| 582 | cmd->colorAttachments[index].loadOp = descriptor->colorAttachments[i].loadOp; |
| 583 | cmd->colorAttachments[index].storeOp = descriptor->colorAttachments[i].storeOp; |
| 584 | cmd->colorAttachments[index].clearColor = |
Corentin Wallez | a838c7d | 2019-09-20 22:59:47 +0000 | [diff] [blame] | 585 | descriptor->colorAttachments[i].clearColor; |
Austin Eng | 4b0b7a5 | 2019-11-21 22:09:41 +0000 | [diff] [blame] | 586 | |
Corentin Wallez | 6b08781 | 2020-10-27 15:35:56 +0000 | [diff] [blame] | 587 | usageTracker.TextureViewUsedAs(view, wgpu::TextureUsage::RenderAttachment); |
Austin Eng | 4b0b7a5 | 2019-11-21 22:09:41 +0000 | [diff] [blame] | 588 | |
| 589 | if (resolveTarget != nullptr) { |
Yunchao He | 23428ea | 2020-05-04 17:10:49 +0000 | [diff] [blame] | 590 | usageTracker.TextureViewUsedAs(resolveTarget, |
Corentin Wallez | 6b08781 | 2020-10-27 15:35:56 +0000 | [diff] [blame] | 591 | wgpu::TextureUsage::RenderAttachment); |
Austin Eng | 4b0b7a5 | 2019-11-21 22:09:41 +0000 | [diff] [blame] | 592 | } |
Austin Eng | fde9490 | 2019-07-24 18:15:24 +0000 | [diff] [blame] | 593 | } |
| 594 | |
Austin Eng | b98f0fa | 2019-07-26 19:08:18 +0000 | [diff] [blame] | 595 | if (cmd->attachmentState->HasDepthStencilAttachment()) { |
Brandon Jones | 5e6a092 | 2021-04-17 01:51:53 +0000 | [diff] [blame] | 596 | TextureViewBase* view = descriptor->depthStencilAttachment->view; |
| 597 | if (view == nullptr) { |
| 598 | view = descriptor->depthStencilAttachment->attachment; |
| 599 | } |
Austin Eng | 4b0b7a5 | 2019-11-21 22:09:41 +0000 | [diff] [blame] | 600 | |
| 601 | cmd->depthStencilAttachment.view = view; |
Austin Eng | fde9490 | 2019-07-24 18:15:24 +0000 | [diff] [blame] | 602 | cmd->depthStencilAttachment.clearDepth = |
| 603 | descriptor->depthStencilAttachment->clearDepth; |
| 604 | cmd->depthStencilAttachment.clearStencil = |
| 605 | descriptor->depthStencilAttachment->clearStencil; |
| 606 | cmd->depthStencilAttachment.depthLoadOp = |
| 607 | descriptor->depthStencilAttachment->depthLoadOp; |
| 608 | cmd->depthStencilAttachment.depthStoreOp = |
| 609 | descriptor->depthStencilAttachment->depthStoreOp; |
| 610 | cmd->depthStencilAttachment.stencilLoadOp = |
| 611 | descriptor->depthStencilAttachment->stencilLoadOp; |
| 612 | cmd->depthStencilAttachment.stencilStoreOp = |
| 613 | descriptor->depthStencilAttachment->stencilStoreOp; |
Austin Eng | 4b0b7a5 | 2019-11-21 22:09:41 +0000 | [diff] [blame] | 614 | |
Corentin Wallez | 6b08781 | 2020-10-27 15:35:56 +0000 | [diff] [blame] | 615 | usageTracker.TextureViewUsedAs(view, wgpu::TextureUsage::RenderAttachment); |
Austin Eng | fde9490 | 2019-07-24 18:15:24 +0000 | [diff] [blame] | 616 | } |
| 617 | |
| 618 | cmd->width = width; |
| 619 | cmd->height = height; |
Austin Eng | fde9490 | 2019-07-24 18:15:24 +0000 | [diff] [blame] | 620 | |
Hao Li | d11f4c3 | 2021-02-02 05:30:50 +0000 | [diff] [blame] | 621 | cmd->occlusionQuerySet = descriptor->occlusionQuerySet; |
| 622 | |
Austin Eng | fde9490 | 2019-07-24 18:15:24 +0000 | [diff] [blame] | 623 | return {}; |
| 624 | }); |
| 625 | |
| 626 | if (success) { |
Corentin Wallez | 95ff834 | 2021-01-27 17:20:16 +0000 | [diff] [blame] | 627 | RenderPassEncoder* passEncoder = new RenderPassEncoder( |
| 628 | device, this, &mEncodingContext, std::move(usageTracker), |
| 629 | std::move(attachmentState), descriptor->occlusionQuerySet, width, height); |
Austin Eng | fde9490 | 2019-07-24 18:15:24 +0000 | [diff] [blame] | 630 | mEncodingContext.EnterPass(passEncoder); |
| 631 | return passEncoder; |
Corentin Wallez | f20f5b9 | 2019-02-20 11:46:16 +0000 | [diff] [blame] | 632 | } |
| 633 | |
Corentin Wallez | 321c122 | 2019-11-13 17:00:37 +0000 | [diff] [blame] | 634 | return RenderPassEncoder::MakeError(device, this, &mEncodingContext); |
Corentin Wallez | e1f0d4e | 2019-02-15 12:54:08 +0000 | [diff] [blame] | 635 | } |
| 636 | |
Corentin Wallez | 2ce4b90 | 2021-03-29 14:02:05 +0000 | [diff] [blame] | 637 | void CommandEncoder::APICopyBufferToBuffer(BufferBase* source, |
| 638 | uint64_t sourceOffset, |
| 639 | BufferBase* destination, |
| 640 | uint64_t destinationOffset, |
| 641 | uint64_t size) { |
Austin Eng | fde9490 | 2019-07-24 18:15:24 +0000 | [diff] [blame] | 642 | mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { |
Corentin Wallez | ecf9347 | 2020-05-05 08:33:55 +0000 | [diff] [blame] | 643 | if (GetDevice()->IsValidationEnabled()) { |
| 644 | DAWN_TRY(GetDevice()->ValidateObject(source)); |
| 645 | DAWN_TRY(GetDevice()->ValidateObject(destination)); |
| 646 | |
Jiawei Shao | 2ae84e9 | 2020-05-19 00:11:11 +0000 | [diff] [blame] | 647 | if (source == destination) { |
| 648 | return DAWN_VALIDATION_ERROR( |
| 649 | "Source and destination cannot be the same buffer."); |
| 650 | } |
| 651 | |
Corentin Wallez | ecf9347 | 2020-05-05 08:33:55 +0000 | [diff] [blame] | 652 | DAWN_TRY(ValidateCopySizeFitsInBuffer(source, sourceOffset, size)); |
| 653 | DAWN_TRY(ValidateCopySizeFitsInBuffer(destination, destinationOffset, size)); |
| 654 | DAWN_TRY(ValidateB2BCopyAlignment(size, sourceOffset, destinationOffset)); |
| 655 | |
| 656 | DAWN_TRY(ValidateCanUseAs(source, wgpu::BufferUsage::CopySrc)); |
| 657 | DAWN_TRY(ValidateCanUseAs(destination, wgpu::BufferUsage::CopyDst)); |
| 658 | |
| 659 | mTopLevelBuffers.insert(source); |
| 660 | mTopLevelBuffers.insert(destination); |
| 661 | } |
Corentin Wallez | f20f5b9 | 2019-02-20 11:46:16 +0000 | [diff] [blame] | 662 | |
Austin Eng | f8a0f82 | 2021-06-10 02:40:18 +0000 | [diff] [blame] | 663 | CopyBufferToBufferCmd* copy = |
| 664 | allocator->Allocate<CopyBufferToBufferCmd>(Command::CopyBufferToBuffer); |
| 665 | copy->source = source; |
| 666 | copy->sourceOffset = sourceOffset; |
| 667 | copy->destination = destination; |
| 668 | copy->destinationOffset = destinationOffset; |
| 669 | copy->size = size; |
Corentin Wallez | f20f5b9 | 2019-02-20 11:46:16 +0000 | [diff] [blame] | 670 | |
Austin Eng | fde9490 | 2019-07-24 18:15:24 +0000 | [diff] [blame] | 671 | return {}; |
| 672 | }); |
Corentin Wallez | e1f0d4e | 2019-02-15 12:54:08 +0000 | [diff] [blame] | 673 | } |
| 674 | |
Corentin Wallez | 2ce4b90 | 2021-03-29 14:02:05 +0000 | [diff] [blame] | 675 | void CommandEncoder::APICopyBufferToTexture(const ImageCopyBuffer* source, |
| 676 | const ImageCopyTexture* destination, |
| 677 | const Extent3D* copySize) { |
Austin Eng | fde9490 | 2019-07-24 18:15:24 +0000 | [diff] [blame] | 678 | mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { |
Corentin Wallez | ecf9347 | 2020-05-05 08:33:55 +0000 | [diff] [blame] | 679 | if (GetDevice()->IsValidationEnabled()) { |
Corentin Wallez | 8091584 | 2021-03-04 18:13:45 +0000 | [diff] [blame] | 680 | DAWN_TRY(ValidateImageCopyBuffer(GetDevice(), *source)); |
Tomek Ponitka | 0f5d496 | 2020-07-07 10:18:51 +0000 | [diff] [blame] | 681 | DAWN_TRY(ValidateCanUseAs(source->buffer, wgpu::BufferUsage::CopySrc)); |
| 682 | |
Brandon Jones | 76e5a9f | 2021-05-13 17:51:23 +0000 | [diff] [blame] | 683 | DAWN_TRY(ValidateImageCopyTexture(GetDevice(), *destination, *copySize)); |
Tomek Ponitka | 0f5d496 | 2020-07-07 10:18:51 +0000 | [diff] [blame] | 684 | DAWN_TRY(ValidateCanUseAs(destination->texture, wgpu::TextureUsage::CopyDst)); |
Austin Eng | f114a68 | 2020-09-01 18:40:18 +0000 | [diff] [blame] | 685 | DAWN_TRY(ValidateTextureSampleCountInBufferCopyCommands(destination->texture)); |
Tomek Ponitka | 0f5d496 | 2020-07-07 10:18:51 +0000 | [diff] [blame] | 686 | |
Kai Ninomiya | 54123a3 | 2020-10-27 19:30:57 +0000 | [diff] [blame] | 687 | DAWN_TRY(ValidateLinearToDepthStencilCopyRestrictions(*destination)); |
Tomek Ponitka | 7365226 | 2020-07-17 09:44:46 +0000 | [diff] [blame] | 688 | // We validate texture copy range before validating linear texture data, |
| 689 | // because in the latter we divide copyExtent.width by blockWidth and |
| 690 | // copyExtent.height by blockHeight while the divisibility conditions are |
| 691 | // checked in validating texture copy range. |
Brandon Jones | 76e5a9f | 2021-05-13 17:51:23 +0000 | [diff] [blame] | 692 | DAWN_TRY(ValidateTextureCopyRange(GetDevice(), *destination, *copySize)); |
Kai Ninomiya | d1bca09 | 2020-10-12 23:13:53 +0000 | [diff] [blame] | 693 | } |
| 694 | const TexelBlockInfo& blockInfo = |
Corentin Wallez | 6298d2b | 2020-10-15 09:05:03 +0000 | [diff] [blame] | 695 | destination->texture->GetFormat().GetAspectInfo(destination->aspect).block; |
Kai Ninomiya | d1bca09 | 2020-10-12 23:13:53 +0000 | [diff] [blame] | 696 | if (GetDevice()->IsValidationEnabled()) { |
Zhaoming Jiang | 1af81e3 | 2021-06-24 05:38:00 +0000 | [diff] [blame] | 697 | DAWN_TRY(ValidateLinearTextureCopyOffset( |
Brandon Jones | aeff235 | 2021-07-04 18:31:29 +0000 | [diff] [blame] | 698 | source->layout, blockInfo, |
| 699 | destination->texture->GetFormat().HasDepthOrStencil())); |
| 700 | DAWN_TRY(ValidateLinearTextureData(source->layout, source->buffer->GetSize(), |
| 701 | blockInfo, *copySize)); |
Tomek Ponitka | 0f5d496 | 2020-07-07 10:18:51 +0000 | [diff] [blame] | 702 | |
| 703 | mTopLevelBuffers.insert(source->buffer); |
| 704 | mTopLevelTextures.insert(destination->texture); |
Corentin Wallez | ecf9347 | 2020-05-05 08:33:55 +0000 | [diff] [blame] | 705 | } |
Corentin Wallez | f20f5b9 | 2019-02-20 11:46:16 +0000 | [diff] [blame] | 706 | |
Brandon Jones | aeff235 | 2021-07-04 18:31:29 +0000 | [diff] [blame] | 707 | TextureDataLayout srcLayout = source->layout; |
Brandon Jones | 76e5a9f | 2021-05-13 17:51:23 +0000 | [diff] [blame] | 708 | ApplyDefaultTextureDataLayoutOptions(&srcLayout, blockInfo, *copySize); |
Tomek Ponitka | 7ce4924 | 2020-08-05 16:43:24 +0000 | [diff] [blame] | 709 | |
Austin Eng | f8a0f82 | 2021-06-10 02:40:18 +0000 | [diff] [blame] | 710 | CopyBufferToTextureCmd* copy = |
| 711 | allocator->Allocate<CopyBufferToTextureCmd>(Command::CopyBufferToTexture); |
| 712 | copy->source.buffer = source->buffer; |
| 713 | copy->source.offset = srcLayout.offset; |
| 714 | copy->source.bytesPerRow = srcLayout.bytesPerRow; |
| 715 | copy->source.rowsPerImage = srcLayout.rowsPerImage; |
| 716 | copy->destination.texture = destination->texture; |
| 717 | copy->destination.origin = destination->origin; |
| 718 | copy->destination.mipLevel = destination->mipLevel; |
| 719 | copy->destination.aspect = |
| 720 | ConvertAspect(destination->texture->GetFormat(), destination->aspect); |
| 721 | copy->copySize = *copySize; |
Corentin Wallez | 984493d | 2020-06-16 03:05:17 +0000 | [diff] [blame] | 722 | |
Austin Eng | fde9490 | 2019-07-24 18:15:24 +0000 | [diff] [blame] | 723 | return {}; |
| 724 | }); |
Corentin Wallez | e1f0d4e | 2019-02-15 12:54:08 +0000 | [diff] [blame] | 725 | } |
| 726 | |
Corentin Wallez | 2ce4b90 | 2021-03-29 14:02:05 +0000 | [diff] [blame] | 727 | void CommandEncoder::APICopyTextureToBuffer(const ImageCopyTexture* source, |
| 728 | const ImageCopyBuffer* destination, |
| 729 | const Extent3D* copySize) { |
Austin Eng | fde9490 | 2019-07-24 18:15:24 +0000 | [diff] [blame] | 730 | mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { |
Corentin Wallez | ecf9347 | 2020-05-05 08:33:55 +0000 | [diff] [blame] | 731 | if (GetDevice()->IsValidationEnabled()) { |
Brandon Jones | 76e5a9f | 2021-05-13 17:51:23 +0000 | [diff] [blame] | 732 | DAWN_TRY(ValidateImageCopyTexture(GetDevice(), *source, *copySize)); |
Tomek Ponitka | 0f5d496 | 2020-07-07 10:18:51 +0000 | [diff] [blame] | 733 | DAWN_TRY(ValidateCanUseAs(source->texture, wgpu::TextureUsage::CopySrc)); |
Austin Eng | f114a68 | 2020-09-01 18:40:18 +0000 | [diff] [blame] | 734 | DAWN_TRY(ValidateTextureSampleCountInBufferCopyCommands(source->texture)); |
Kai Ninomiya | 54123a3 | 2020-10-27 19:30:57 +0000 | [diff] [blame] | 735 | DAWN_TRY(ValidateTextureDepthStencilToBufferCopyRestrictions(*source)); |
Tomek Ponitka | 0f5d496 | 2020-07-07 10:18:51 +0000 | [diff] [blame] | 736 | |
Corentin Wallez | 8091584 | 2021-03-04 18:13:45 +0000 | [diff] [blame] | 737 | DAWN_TRY(ValidateImageCopyBuffer(GetDevice(), *destination)); |
Tomek Ponitka | 0f5d496 | 2020-07-07 10:18:51 +0000 | [diff] [blame] | 738 | DAWN_TRY(ValidateCanUseAs(destination->buffer, wgpu::BufferUsage::CopyDst)); |
| 739 | |
Tomek Ponitka | 7365226 | 2020-07-17 09:44:46 +0000 | [diff] [blame] | 740 | // We validate texture copy range before validating linear texture data, |
| 741 | // because in the latter we divide copyExtent.width by blockWidth and |
| 742 | // copyExtent.height by blockHeight while the divisibility conditions are |
| 743 | // checked in validating texture copy range. |
Brandon Jones | 76e5a9f | 2021-05-13 17:51:23 +0000 | [diff] [blame] | 744 | DAWN_TRY(ValidateTextureCopyRange(GetDevice(), *source, *copySize)); |
Kai Ninomiya | d1bca09 | 2020-10-12 23:13:53 +0000 | [diff] [blame] | 745 | } |
| 746 | const TexelBlockInfo& blockInfo = |
Corentin Wallez | 6298d2b | 2020-10-15 09:05:03 +0000 | [diff] [blame] | 747 | source->texture->GetFormat().GetAspectInfo(source->aspect).block; |
Kai Ninomiya | d1bca09 | 2020-10-12 23:13:53 +0000 | [diff] [blame] | 748 | if (GetDevice()->IsValidationEnabled()) { |
Zhaoming Jiang | 1af81e3 | 2021-06-24 05:38:00 +0000 | [diff] [blame] | 749 | DAWN_TRY(ValidateLinearTextureCopyOffset( |
Brandon Jones | aeff235 | 2021-07-04 18:31:29 +0000 | [diff] [blame] | 750 | destination->layout, blockInfo, |
| 751 | source->texture->GetFormat().HasDepthOrStencil())); |
| 752 | DAWN_TRY(ValidateLinearTextureData( |
| 753 | destination->layout, destination->buffer->GetSize(), blockInfo, *copySize)); |
Tomek Ponitka | 0f5d496 | 2020-07-07 10:18:51 +0000 | [diff] [blame] | 754 | |
| 755 | mTopLevelTextures.insert(source->texture); |
| 756 | mTopLevelBuffers.insert(destination->buffer); |
Corentin Wallez | ecf9347 | 2020-05-05 08:33:55 +0000 | [diff] [blame] | 757 | } |
Corentin Wallez | f20f5b9 | 2019-02-20 11:46:16 +0000 | [diff] [blame] | 758 | |
Brandon Jones | aeff235 | 2021-07-04 18:31:29 +0000 | [diff] [blame] | 759 | TextureDataLayout dstLayout = destination->layout; |
Brandon Jones | 76e5a9f | 2021-05-13 17:51:23 +0000 | [diff] [blame] | 760 | ApplyDefaultTextureDataLayoutOptions(&dstLayout, blockInfo, *copySize); |
Tomek Ponitka | 7ce4924 | 2020-08-05 16:43:24 +0000 | [diff] [blame] | 761 | |
Austin Eng | f8a0f82 | 2021-06-10 02:40:18 +0000 | [diff] [blame] | 762 | CopyTextureToBufferCmd* copy = |
| 763 | allocator->Allocate<CopyTextureToBufferCmd>(Command::CopyTextureToBuffer); |
| 764 | copy->source.texture = source->texture; |
| 765 | copy->source.origin = source->origin; |
| 766 | copy->source.mipLevel = source->mipLevel; |
| 767 | copy->source.aspect = ConvertAspect(source->texture->GetFormat(), source->aspect); |
| 768 | copy->destination.buffer = destination->buffer; |
| 769 | copy->destination.offset = dstLayout.offset; |
| 770 | copy->destination.bytesPerRow = dstLayout.bytesPerRow; |
| 771 | copy->destination.rowsPerImage = dstLayout.rowsPerImage; |
| 772 | copy->copySize = *copySize; |
Corentin Wallez | 984493d | 2020-06-16 03:05:17 +0000 | [diff] [blame] | 773 | |
Austin Eng | fde9490 | 2019-07-24 18:15:24 +0000 | [diff] [blame] | 774 | return {}; |
| 775 | }); |
Corentin Wallez | e1f0d4e | 2019-02-15 12:54:08 +0000 | [diff] [blame] | 776 | } |
| 777 | |
Corentin Wallez | 2ce4b90 | 2021-03-29 14:02:05 +0000 | [diff] [blame] | 778 | void CommandEncoder::APICopyTextureToTexture(const ImageCopyTexture* source, |
| 779 | const ImageCopyTexture* destination, |
| 780 | const Extent3D* copySize) { |
Juanmi | f00c68a | 2021-08-05 22:55:09 +0000 | [diff] [blame] | 781 | APICopyTextureToTextureHelper<false>(source, destination, copySize); |
| 782 | } |
| 783 | |
| 784 | void CommandEncoder::APICopyTextureToTextureInternal(const ImageCopyTexture* source, |
| 785 | const ImageCopyTexture* destination, |
| 786 | const Extent3D* copySize) { |
| 787 | APICopyTextureToTextureHelper<true>(source, destination, copySize); |
| 788 | } |
| 789 | |
| 790 | template <bool Internal> |
| 791 | void CommandEncoder::APICopyTextureToTextureHelper(const ImageCopyTexture* source, |
| 792 | const ImageCopyTexture* destination, |
| 793 | const Extent3D* copySize) { |
Austin Eng | fde9490 | 2019-07-24 18:15:24 +0000 | [diff] [blame] | 794 | mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { |
Corentin Wallez | ecf9347 | 2020-05-05 08:33:55 +0000 | [diff] [blame] | 795 | if (GetDevice()->IsValidationEnabled()) { |
| 796 | DAWN_TRY(GetDevice()->ValidateObject(source->texture)); |
| 797 | DAWN_TRY(GetDevice()->ValidateObject(destination->texture)); |
| 798 | |
Brandon Jones | 76e5a9f | 2021-05-13 17:51:23 +0000 | [diff] [blame] | 799 | DAWN_TRY(ValidateImageCopyTexture(GetDevice(), *source, *copySize)); |
| 800 | DAWN_TRY(ValidateImageCopyTexture(GetDevice(), *destination, *copySize)); |
Austin Eng | ea82272 | 2020-09-02 18:50:09 +0000 | [diff] [blame] | 801 | |
Corentin Wallez | ecf9347 | 2020-05-05 08:33:55 +0000 | [diff] [blame] | 802 | DAWN_TRY( |
Brandon Jones | 76e5a9f | 2021-05-13 17:51:23 +0000 | [diff] [blame] | 803 | ValidateTextureToTextureCopyRestrictions(*source, *destination, *copySize)); |
Corentin Wallez | ecf9347 | 2020-05-05 08:33:55 +0000 | [diff] [blame] | 804 | |
Brandon Jones | 76e5a9f | 2021-05-13 17:51:23 +0000 | [diff] [blame] | 805 | DAWN_TRY(ValidateTextureCopyRange(GetDevice(), *source, *copySize)); |
| 806 | DAWN_TRY(ValidateTextureCopyRange(GetDevice(), *destination, *copySize)); |
Corentin Wallez | ecf9347 | 2020-05-05 08:33:55 +0000 | [diff] [blame] | 807 | |
Juanmi | f00c68a | 2021-08-05 22:55:09 +0000 | [diff] [blame] | 808 | // For internal usages (CopyToCopyInternal) we don't care if the user has added |
| 809 | // CopySrc as a usage for this texture, but we will always add it internally. |
| 810 | if (Internal) { |
| 811 | DAWN_TRY( |
| 812 | ValidateInternalCanUseAs(source->texture, wgpu::TextureUsage::CopySrc)); |
| 813 | DAWN_TRY(ValidateInternalCanUseAs(destination->texture, |
| 814 | wgpu::TextureUsage::CopyDst)); |
| 815 | } else { |
| 816 | DAWN_TRY(ValidateCanUseAs(source->texture, wgpu::TextureUsage::CopySrc)); |
| 817 | DAWN_TRY(ValidateCanUseAs(destination->texture, wgpu::TextureUsage::CopyDst)); |
| 818 | } |
Corentin Wallez | ecf9347 | 2020-05-05 08:33:55 +0000 | [diff] [blame] | 819 | |
| 820 | mTopLevelTextures.insert(source->texture); |
| 821 | mTopLevelTextures.insert(destination->texture); |
| 822 | } |
Brandon Jones | d3d3aa0 | 2019-03-26 11:06:23 +0000 | [diff] [blame] | 823 | |
Austin Eng | f8a0f82 | 2021-06-10 02:40:18 +0000 | [diff] [blame] | 824 | CopyTextureToTextureCmd* copy = |
| 825 | allocator->Allocate<CopyTextureToTextureCmd>(Command::CopyTextureToTexture); |
| 826 | copy->source.texture = source->texture; |
| 827 | copy->source.origin = source->origin; |
| 828 | copy->source.mipLevel = source->mipLevel; |
| 829 | copy->source.aspect = ConvertAspect(source->texture->GetFormat(), source->aspect); |
| 830 | copy->destination.texture = destination->texture; |
| 831 | copy->destination.origin = destination->origin; |
| 832 | copy->destination.mipLevel = destination->mipLevel; |
| 833 | copy->destination.aspect = |
| 834 | ConvertAspect(destination->texture->GetFormat(), destination->aspect); |
| 835 | copy->copySize = *copySize; |
Brandon Jones | d3d3aa0 | 2019-03-26 11:06:23 +0000 | [diff] [blame] | 836 | |
Austin Eng | fde9490 | 2019-07-24 18:15:24 +0000 | [diff] [blame] | 837 | return {}; |
| 838 | }); |
Brandon Jones | d3d3aa0 | 2019-03-26 11:06:23 +0000 | [diff] [blame] | 839 | } |
| 840 | |
Corentin Wallez | 2ce4b90 | 2021-03-29 14:02:05 +0000 | [diff] [blame] | 841 | void CommandEncoder::APIInjectValidationError(const char* message) { |
Austin Eng | 464aaeb | 2020-11-14 01:24:03 +0000 | [diff] [blame] | 842 | if (mEncodingContext.CheckCurrentEncoder(this)) { |
Corentin Wallez | d98b307 | 2021-05-05 17:37:43 +0000 | [diff] [blame] | 843 | mEncodingContext.HandleError(DAWN_VALIDATION_ERROR(message)); |
Austin Eng | 464aaeb | 2020-11-14 01:24:03 +0000 | [diff] [blame] | 844 | } |
| 845 | } |
| 846 | |
Corentin Wallez | 2ce4b90 | 2021-03-29 14:02:05 +0000 | [diff] [blame] | 847 | void CommandEncoder::APIInsertDebugMarker(const char* groupLabel) { |
Corentin Wallez | b8ea84c | 2019-09-10 08:20:40 +0000 | [diff] [blame] | 848 | mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { |
| 849 | InsertDebugMarkerCmd* cmd = |
| 850 | allocator->Allocate<InsertDebugMarkerCmd>(Command::InsertDebugMarker); |
| 851 | cmd->length = strlen(groupLabel); |
| 852 | |
| 853 | char* label = allocator->AllocateData<char>(cmd->length + 1); |
| 854 | memcpy(label, groupLabel, cmd->length + 1); |
| 855 | |
| 856 | return {}; |
| 857 | }); |
| 858 | } |
| 859 | |
Corentin Wallez | 2ce4b90 | 2021-03-29 14:02:05 +0000 | [diff] [blame] | 860 | void CommandEncoder::APIPopDebugGroup() { |
Corentin Wallez | b8ea84c | 2019-09-10 08:20:40 +0000 | [diff] [blame] | 861 | mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { |
Corentin Wallez | 7ffaa21 | 2021-01-27 16:03:32 +0000 | [diff] [blame] | 862 | if (GetDevice()->IsValidationEnabled()) { |
| 863 | if (mDebugGroupStackSize == 0) { |
| 864 | return DAWN_VALIDATION_ERROR("Pop must be balanced by a corresponding Push."); |
| 865 | } |
| 866 | } |
Corentin Wallez | b8ea84c | 2019-09-10 08:20:40 +0000 | [diff] [blame] | 867 | allocator->Allocate<PopDebugGroupCmd>(Command::PopDebugGroup); |
Corentin Wallez | 7ffaa21 | 2021-01-27 16:03:32 +0000 | [diff] [blame] | 868 | mDebugGroupStackSize--; |
Corentin Wallez | b8ea84c | 2019-09-10 08:20:40 +0000 | [diff] [blame] | 869 | |
| 870 | return {}; |
| 871 | }); |
| 872 | } |
| 873 | |
Corentin Wallez | 2ce4b90 | 2021-03-29 14:02:05 +0000 | [diff] [blame] | 874 | void CommandEncoder::APIPushDebugGroup(const char* groupLabel) { |
Corentin Wallez | b8ea84c | 2019-09-10 08:20:40 +0000 | [diff] [blame] | 875 | mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { |
| 876 | PushDebugGroupCmd* cmd = |
| 877 | allocator->Allocate<PushDebugGroupCmd>(Command::PushDebugGroup); |
| 878 | cmd->length = strlen(groupLabel); |
| 879 | |
| 880 | char* label = allocator->AllocateData<char>(cmd->length + 1); |
| 881 | memcpy(label, groupLabel, cmd->length + 1); |
| 882 | |
Corentin Wallez | 7ffaa21 | 2021-01-27 16:03:32 +0000 | [diff] [blame] | 883 | mDebugGroupStackSize++; |
| 884 | |
Corentin Wallez | b8ea84c | 2019-09-10 08:20:40 +0000 | [diff] [blame] | 885 | return {}; |
| 886 | }); |
| 887 | } |
| 888 | |
Corentin Wallez | 2ce4b90 | 2021-03-29 14:02:05 +0000 | [diff] [blame] | 889 | void CommandEncoder::APIResolveQuerySet(QuerySetBase* querySet, |
| 890 | uint32_t firstQuery, |
| 891 | uint32_t queryCount, |
| 892 | BufferBase* destination, |
| 893 | uint64_t destinationOffset) { |
Hao Li | 5c89c8d | 2020-07-17 09:02:46 +0000 | [diff] [blame] | 894 | mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { |
| 895 | if (GetDevice()->IsValidationEnabled()) { |
| 896 | DAWN_TRY(GetDevice()->ValidateObject(querySet)); |
| 897 | DAWN_TRY(GetDevice()->ValidateObject(destination)); |
| 898 | |
| 899 | DAWN_TRY(ValidateQuerySetResolve(querySet, firstQuery, queryCount, destination, |
| 900 | destinationOffset)); |
| 901 | |
| 902 | DAWN_TRY(ValidateCanUseAs(destination, wgpu::BufferUsage::QueryResolve)); |
| 903 | |
| 904 | TrackUsedQuerySet(querySet); |
| 905 | mTopLevelBuffers.insert(destination); |
| 906 | } |
| 907 | |
| 908 | ResolveQuerySetCmd* cmd = |
| 909 | allocator->Allocate<ResolveQuerySetCmd>(Command::ResolveQuerySet); |
| 910 | cmd->querySet = querySet; |
| 911 | cmd->firstQuery = firstQuery; |
| 912 | cmd->queryCount = queryCount; |
| 913 | cmd->destination = destination; |
| 914 | cmd->destinationOffset = destinationOffset; |
| 915 | |
Hao Li | 6f833b7 | 2021-01-14 03:26:08 +0000 | [diff] [blame] | 916 | // Encode internal compute pipeline for timestamp query |
Corentin Wallez | ad879f5 | 2021-03-31 19:31:42 +0000 | [diff] [blame] | 917 | if (querySet->GetQueryType() == wgpu::QueryType::Timestamp) { |
Hao Li | 880a3d6 | 2021-05-18 01:13:08 +0000 | [diff] [blame] | 918 | DAWN_TRY(EncodeTimestampsToNanosecondsConversion( |
| 919 | this, querySet, firstQuery, queryCount, destination, destinationOffset)); |
Hao Li | 6f833b7 | 2021-01-14 03:26:08 +0000 | [diff] [blame] | 920 | } |
| 921 | |
Hao Li | 5c89c8d | 2020-07-17 09:02:46 +0000 | [diff] [blame] | 922 | return {}; |
| 923 | }); |
| 924 | } |
| 925 | |
Corentin Wallez | 2ce4b90 | 2021-03-29 14:02:05 +0000 | [diff] [blame] | 926 | void CommandEncoder::APIWriteTimestamp(QuerySetBase* querySet, uint32_t queryIndex) { |
Hao Li | 5191adc | 2020-07-01 10:48:16 +0000 | [diff] [blame] | 927 | mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError { |
| 928 | if (GetDevice()->IsValidationEnabled()) { |
| 929 | DAWN_TRY(GetDevice()->ValidateObject(querySet)); |
Hao Li | 575729e | 2020-11-16 02:24:06 +0000 | [diff] [blame] | 930 | DAWN_TRY(ValidateTimestampQuery(querySet, queryIndex)); |
Hao Li | 5191adc | 2020-07-01 10:48:16 +0000 | [diff] [blame] | 931 | } |
| 932 | |
Hao Li | 575729e | 2020-11-16 02:24:06 +0000 | [diff] [blame] | 933 | TrackQueryAvailability(querySet, queryIndex); |
Hao Li | e2cbcc9 | 2020-10-21 08:38:31 +0000 | [diff] [blame] | 934 | |
Hao Li | 5191adc | 2020-07-01 10:48:16 +0000 | [diff] [blame] | 935 | WriteTimestampCmd* cmd = |
| 936 | allocator->Allocate<WriteTimestampCmd>(Command::WriteTimestamp); |
| 937 | cmd->querySet = querySet; |
| 938 | cmd->queryIndex = queryIndex; |
| 939 | |
| 940 | return {}; |
| 941 | }); |
| 942 | } |
| 943 | |
Corentin Wallez | 2ce4b90 | 2021-03-29 14:02:05 +0000 | [diff] [blame] | 944 | CommandBufferBase* CommandEncoder::APIFinish(const CommandBufferDescriptor* descriptor) { |
Corentin Wallez | 50f9958 | 2021-03-31 18:36:32 +0000 | [diff] [blame] | 945 | Ref<CommandBufferBase> commandBuffer; |
| 946 | if (GetDevice()->ConsumedError(FinishInternal(descriptor), &commandBuffer)) { |
| 947 | return CommandBufferBase::MakeError(GetDevice()); |
| 948 | } |
| 949 | ASSERT(!IsError()); |
| 950 | return commandBuffer.Detach(); |
| 951 | } |
| 952 | |
| 953 | ResultOrError<Ref<CommandBufferBase>> CommandEncoder::FinishInternal( |
| 954 | const CommandBufferDescriptor* descriptor) { |
Austin Eng | 4b0b7a5 | 2019-11-21 22:09:41 +0000 | [diff] [blame] | 955 | DeviceBase* device = GetDevice(); |
Corentin Wallez | 50f9958 | 2021-03-31 18:36:32 +0000 | [diff] [blame] | 956 | |
Austin Eng | 4b0b7a5 | 2019-11-21 22:09:41 +0000 | [diff] [blame] | 957 | // Even if mEncodingContext.Finish() validation fails, calling it will mutate the internal |
| 958 | // state of the encoding context. The internal state is set to finished, and subsequent |
| 959 | // calls to encode commands will generate errors. |
Corentin Wallez | 50f9958 | 2021-03-31 18:36:32 +0000 | [diff] [blame] | 960 | DAWN_TRY(mEncodingContext.Finish()); |
| 961 | DAWN_TRY(device->ValidateIsAlive()); |
| 962 | |
| 963 | if (device->IsValidationEnabled()) { |
Corentin Wallez | 2dd2d67 | 2021-05-05 15:41:13 +0000 | [diff] [blame] | 964 | DAWN_TRY(ValidateFinish()); |
Corentin Wallez | e1f0d4e | 2019-02-15 12:54:08 +0000 | [diff] [blame] | 965 | } |
Austin Eng | 4b0b7a5 | 2019-11-21 22:09:41 +0000 | [diff] [blame] | 966 | return device->CreateCommandBuffer(this, descriptor); |
Corentin Wallez | e1f0d4e | 2019-02-15 12:54:08 +0000 | [diff] [blame] | 967 | } |
| 968 | |
Corentin Wallez | f20f5b9 | 2019-02-20 11:46:16 +0000 | [diff] [blame] | 969 | // Implementation of the command buffer validation that can be precomputed before submit |
Corentin Wallez | 2dd2d67 | 2021-05-05 15:41:13 +0000 | [diff] [blame] | 970 | MaybeError CommandEncoder::ValidateFinish() const { |
Corentin Wallez | 321c122 | 2019-11-13 17:00:37 +0000 | [diff] [blame] | 971 | TRACE_EVENT0(GetDevice()->GetPlatform(), Validation, "CommandEncoder::ValidateFinish"); |
Corentin Wallez | e1f0d4e | 2019-02-15 12:54:08 +0000 | [diff] [blame] | 972 | DAWN_TRY(GetDevice()->ValidateObject(this)); |
Corentin Wallez | f20f5b9 | 2019-02-20 11:46:16 +0000 | [diff] [blame] | 973 | |
Corentin Wallez | ec7ea6a | 2021-05-05 19:55:23 +0000 | [diff] [blame] | 974 | for (const RenderPassResourceUsage& passUsage : mEncodingContext.GetRenderPassUsages()) { |
Corentin Wallez | 2dd2d67 | 2021-05-05 15:41:13 +0000 | [diff] [blame] | 975 | DAWN_TRY(ValidateSyncScopeResourceUsage(passUsage)); |
Austin Eng | 4b0b7a5 | 2019-11-21 22:09:41 +0000 | [diff] [blame] | 976 | } |
Corentin Wallez | 76732ab | 2021-05-06 19:20:14 +0000 | [diff] [blame] | 977 | |
| 978 | for (const ComputePassResourceUsage& passUsage : mEncodingContext.GetComputePassUsages()) { |
| 979 | for (const SyncScopeResourceUsage& scope : passUsage.dispatchUsages) { |
| 980 | DAWN_TRY(ValidateSyncScopeResourceUsage(scope)); |
| 981 | } |
| 982 | } |
Corentin Wallez | f20f5b9 | 2019-02-20 11:46:16 +0000 | [diff] [blame] | 983 | |
Corentin Wallez | 7ffaa21 | 2021-01-27 16:03:32 +0000 | [diff] [blame] | 984 | if (mDebugGroupStackSize != 0) { |
| 985 | return DAWN_VALIDATION_ERROR("Each Push must be balanced by a corresponding Pop."); |
| 986 | } |
Corentin Wallez | b8ea84c | 2019-09-10 08:20:40 +0000 | [diff] [blame] | 987 | |
Corentin Wallez | e1f0d4e | 2019-02-15 12:54:08 +0000 | [diff] [blame] | 988 | return {}; |
| 989 | } |
| 990 | |
Corentin Wallez | e1f0d4e | 2019-02-15 12:54:08 +0000 | [diff] [blame] | 991 | } // namespace dawn_native |