blob: 01a5b62a4f52ee41243f5378050810503f34bf97 [file] [log] [blame]
Corentin Walleze1f0d4e2019-02-15 12:54:08 +00001// 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 Wallezf20f5b92019-02-20 11:46:16 +000017#include "common/BitSetIterator.h"
18#include "dawn_native/BindGroup.h"
19#include "dawn_native/Buffer.h"
Corentin Walleze1f0d4e2019-02-15 12:54:08 +000020#include "dawn_native/CommandBuffer.h"
Corentin Wallezf20f5b92019-02-20 11:46:16 +000021#include "dawn_native/CommandBufferStateTracker.h"
Austin Eng3318caa2019-08-13 00:22:28 +000022#include "dawn_native/CommandValidation.h"
Corentin Wallezf20f5b92019-02-20 11:46:16 +000023#include "dawn_native/Commands.h"
24#include "dawn_native/ComputePassEncoder.h"
Corentin Walleze1f0d4e2019-02-15 12:54:08 +000025#include "dawn_native/Device.h"
Corentin Wallezf20f5b92019-02-20 11:46:16 +000026#include "dawn_native/ErrorData.h"
Hao Li5191adc2020-07-01 10:48:16 +000027#include "dawn_native/QuerySet.h"
Corentin Wallezf20f5b92019-02-20 11:46:16 +000028#include "dawn_native/RenderPassEncoder.h"
29#include "dawn_native/RenderPipeline.h"
Jiawei Shao51c347a2019-12-12 01:29:01 +000030#include "dawn_native/ValidationUtils_autogen.h"
Austin Eng73d5bb52019-10-28 23:15:40 +000031#include "dawn_platform/DawnPlatform.h"
Austin Engd4ce7362019-08-13 19:00:34 +000032#include "dawn_platform/tracing/TraceEvent.h"
Corentin Wallezf20f5b92019-02-20 11:46:16 +000033
Corentin Walleze51f8dd2020-02-18 02:44:05 +000034#include <cmath>
Corentin Wallezf20f5b92019-02-20 11:46:16 +000035#include <map>
Corentin Walleze1f0d4e2019-02-15 12:54:08 +000036
37namespace dawn_native {
38
Corentin Wallezf20f5b92019-02-20 11:46:16 +000039 namespace {
40
Corentin Wallezecf93472020-05-05 08:33:55 +000041 MaybeError ValidateB2BCopyAlignment(uint64_t dataSize,
42 uint64_t srcOffset,
43 uint64_t dstOffset) {
Yan, Shaobo738567f2019-02-27 02:46:27 +000044 // Copy size must be a multiple of 4 bytes on macOS.
45 if (dataSize % 4 != 0) {
46 return DAWN_VALIDATION_ERROR("Copy size must be a multiple of 4 bytes");
47 }
48
49 // SourceOffset and destinationOffset must be multiples of 4 bytes on macOS.
50 if (srcOffset % 4 != 0 || dstOffset % 4 != 0) {
51 return DAWN_VALIDATION_ERROR(
52 "Source offset and destination offset must be multiples of 4 bytes");
53 }
54
55 return {};
56 }
57
Jiawei Shao081d5c22019-03-04 12:01:59 +000058 MaybeError ValidateTextureSampleCountInCopyCommands(const TextureBase* texture) {
59 if (texture->GetSampleCount() > 1) {
60 return DAWN_VALIDATION_ERROR("The sample count of textures must be 1");
61 }
62
63 return {};
64 }
65
Corentin Wallezecf93472020-05-05 08:33:55 +000066 MaybeError ValidateEntireSubresourceCopied(const TextureCopyView& src,
67 const TextureCopyView& dst,
Brandon Jonesd3d3aa02019-03-26 11:06:23 +000068 const Extent3D& copySize) {
Corentin Wallezecf93472020-05-05 08:33:55 +000069 Extent3D srcSize = src.texture->GetSize();
Brandon Jonesd3d3aa02019-03-26 11:06:23 +000070
Austin Eng2dfc42d2020-06-01 16:19:02 +000071 ASSERT(src.texture->GetDimension() == wgpu::TextureDimension::e2D &&
72 dst.texture->GetDimension() == wgpu::TextureDimension::e2D);
Corentin Wallez984493d2020-06-16 03:05:17 +000073 if (dst.origin.x != 0 || dst.origin.y != 0 || srcSize.width != copySize.width ||
74 srcSize.height != copySize.height) {
Brandon Jonesd3d3aa02019-03-26 11:06:23 +000075 return DAWN_VALIDATION_ERROR(
76 "The entire subresource must be copied when using a depth/stencil texture or "
77 "when samples are greater than 1.");
78 }
79
80 return {};
81 }
82
Corentin Wallezecf93472020-05-05 08:33:55 +000083 MaybeError ValidateTextureToTextureCopyRestrictions(const TextureCopyView& src,
84 const TextureCopyView& dst,
Brandon Jonesd3d3aa02019-03-26 11:06:23 +000085 const Extent3D& copySize) {
Corentin Wallezecf93472020-05-05 08:33:55 +000086 const uint32_t srcSamples = src.texture->GetSampleCount();
87 const uint32_t dstSamples = dst.texture->GetSampleCount();
Brandon Jonesd3d3aa02019-03-26 11:06:23 +000088
89 if (srcSamples != dstSamples) {
90 return DAWN_VALIDATION_ERROR(
91 "Source and destination textures must have matching sample counts.");
92 } else if (srcSamples > 1) {
93 // D3D12 requires entire subresource to be copied when using CopyTextureRegion when
94 // samples > 1.
95 DAWN_TRY(ValidateEntireSubresourceCopied(src, dst, copySize));
96 }
97
Corentin Wallezecf93472020-05-05 08:33:55 +000098 if (src.texture->GetFormat().format != dst.texture->GetFormat().format) {
Brandon Jonesd3d3aa02019-03-26 11:06:23 +000099 // Metal requires texture-to-texture copies be the same format
100 return DAWN_VALIDATION_ERROR("Source and destination texture formats must match.");
Corentin Walleza92f83b2019-06-21 10:16:15 +0000101 }
102
Corentin Wallezecf93472020-05-05 08:33:55 +0000103 if (src.texture->GetFormat().HasDepthOrStencil()) {
Brandon Jonesd3d3aa02019-03-26 11:06:23 +0000104 // D3D12 requires entire subresource to be copied when using CopyTextureRegion is
105 // used with depth/stencil.
106 DAWN_TRY(ValidateEntireSubresourceCopied(src, dst, copySize));
107 }
108
Jiawei Shaoe472c452020-06-08 11:30:01 +0000109 if (src.texture == dst.texture && src.mipLevel == dst.mipLevel) {
110 ASSERT(src.texture->GetDimension() == wgpu::TextureDimension::e2D &&
111 dst.texture->GetDimension() == wgpu::TextureDimension::e2D);
Corentin Wallez984493d2020-06-16 03:05:17 +0000112 if (IsRangeOverlapped(src.origin.z, dst.origin.z, copySize.depth)) {
Jiawei Shaoe472c452020-06-08 11:30:01 +0000113 return DAWN_VALIDATION_ERROR(
114 "Copy subresources cannot be overlapped when copying within the same "
115 "texture.");
116 }
117 }
118
Brandon Jonesd3d3aa02019-03-26 11:06:23 +0000119 return {};
120 }
121
Austin Eng4b0b7a52019-11-21 22:09:41 +0000122 MaybeError ValidateCanUseAs(const BufferBase* buffer, wgpu::BufferUsage usage) {
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000123 ASSERT(wgpu::HasZeroOrOneBits(usage));
Corentin Wallezf20f5b92019-02-20 11:46:16 +0000124 if (!(buffer->GetUsage() & usage)) {
125 return DAWN_VALIDATION_ERROR("buffer doesn't have the required usage.");
126 }
127
128 return {};
129 }
130
Austin Eng4b0b7a52019-11-21 22:09:41 +0000131 MaybeError ValidateCanUseAs(const TextureBase* texture, wgpu::TextureUsage usage) {
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000132 ASSERT(wgpu::HasZeroOrOneBits(usage));
Corentin Wallezf20f5b92019-02-20 11:46:16 +0000133 if (!(texture->GetUsage() & usage)) {
134 return DAWN_VALIDATION_ERROR("texture doesn't have the required usage.");
135 }
136
137 return {};
138 }
139
Jiawei Shaob2c50232019-02-27 09:21:56 +0000140 MaybeError ValidateAttachmentArrayLayersAndLevelCount(const TextureViewBase* attachment) {
141 // Currently we do not support layered rendering.
142 if (attachment->GetLayerCount() > 1) {
143 return DAWN_VALIDATION_ERROR(
144 "The layer count of the texture view used as attachment cannot be greater than "
145 "1");
146 }
147
148 if (attachment->GetLevelCount() > 1) {
149 return DAWN_VALIDATION_ERROR(
150 "The mipmap level count of the texture view used as attachment cannot be "
151 "greater than 1");
152 }
153
154 return {};
155 }
156
157 MaybeError ValidateOrSetAttachmentSize(const TextureViewBase* attachment,
158 uint32_t* width,
159 uint32_t* height) {
160 const Extent3D& textureSize = attachment->GetTexture()->GetSize();
161 const uint32_t attachmentWidth = textureSize.width >> attachment->GetBaseMipLevel();
162 const uint32_t attachmentHeight = textureSize.height >> attachment->GetBaseMipLevel();
163
164 if (*width == 0) {
165 DAWN_ASSERT(*height == 0);
166 *width = attachmentWidth;
167 *height = attachmentHeight;
168 DAWN_ASSERT(*width != 0 && *height != 0);
169 } else if (*width != attachmentWidth || *height != attachmentHeight) {
170 return DAWN_VALIDATION_ERROR("Attachment size mismatch");
171 }
172
173 return {};
174 }
175
Jiawei Shao1e1c13e2019-03-11 18:41:02 +0000176 MaybeError ValidateOrSetColorAttachmentSampleCount(const TextureViewBase* colorAttachment,
177 uint32_t* sampleCount) {
178 if (*sampleCount == 0) {
179 *sampleCount = colorAttachment->GetTexture()->GetSampleCount();
180 DAWN_ASSERT(*sampleCount != 0);
181 } else if (*sampleCount != colorAttachment->GetTexture()->GetSampleCount()) {
182 return DAWN_VALIDATION_ERROR("Color attachment sample counts mismatch");
183 }
184
185 return {};
186 }
187
188 MaybeError ValidateResolveTarget(
189 const DeviceBase* device,
Corentin Walleza838c7d2019-09-20 22:59:47 +0000190 const RenderPassColorAttachmentDescriptor& colorAttachment) {
191 if (colorAttachment.resolveTarget == nullptr) {
Jiawei Shao1e1c13e2019-03-11 18:41:02 +0000192 return {};
193 }
194
Corentin Walleza838c7d2019-09-20 22:59:47 +0000195 const TextureViewBase* resolveTarget = colorAttachment.resolveTarget;
196 const TextureViewBase* attachment = colorAttachment.attachment;
197 DAWN_TRY(device->ValidateObject(colorAttachment.resolveTarget));
Jiawei Shao1e1c13e2019-03-11 18:41:02 +0000198
Corentin Walleza838c7d2019-09-20 22:59:47 +0000199 if (!attachment->GetTexture()->IsMultisampledTexture()) {
Jiawei Shao1e1c13e2019-03-11 18:41:02 +0000200 return DAWN_VALIDATION_ERROR(
201 "Cannot set resolve target when the sample count of the color attachment is 1");
202 }
203
Corentin Walleza838c7d2019-09-20 22:59:47 +0000204 if (resolveTarget->GetTexture()->IsMultisampledTexture()) {
Jiawei Shao1e1c13e2019-03-11 18:41:02 +0000205 return DAWN_VALIDATION_ERROR("Cannot use multisampled texture as resolve target");
206 }
207
Corentin Walleza838c7d2019-09-20 22:59:47 +0000208 if (resolveTarget->GetLayerCount() > 1) {
Jiawei Shao1e1c13e2019-03-11 18:41:02 +0000209 return DAWN_VALIDATION_ERROR(
210 "The array layer count of the resolve target must be 1");
211 }
212
Corentin Walleza838c7d2019-09-20 22:59:47 +0000213 if (resolveTarget->GetLevelCount() > 1) {
Jiawei Shao1e1c13e2019-03-11 18:41:02 +0000214 return DAWN_VALIDATION_ERROR("The mip level count of the resolve target must be 1");
215 }
216
Corentin Walleza838c7d2019-09-20 22:59:47 +0000217 uint32_t colorAttachmentBaseMipLevel = attachment->GetBaseMipLevel();
218 const Extent3D& colorTextureSize = attachment->GetTexture()->GetSize();
Jiawei Shao1e1c13e2019-03-11 18:41:02 +0000219 uint32_t colorAttachmentWidth = colorTextureSize.width >> colorAttachmentBaseMipLevel;
220 uint32_t colorAttachmentHeight = colorTextureSize.height >> colorAttachmentBaseMipLevel;
221
Corentin Walleza838c7d2019-09-20 22:59:47 +0000222 uint32_t resolveTargetBaseMipLevel = resolveTarget->GetBaseMipLevel();
223 const Extent3D& resolveTextureSize = resolveTarget->GetTexture()->GetSize();
Jiawei Shao1e1c13e2019-03-11 18:41:02 +0000224 uint32_t resolveTargetWidth = resolveTextureSize.width >> resolveTargetBaseMipLevel;
225 uint32_t resolveTargetHeight = resolveTextureSize.height >> resolveTargetBaseMipLevel;
226 if (colorAttachmentWidth != resolveTargetWidth ||
227 colorAttachmentHeight != resolveTargetHeight) {
228 return DAWN_VALIDATION_ERROR(
229 "The size of the resolve target must be the same as the color attachment");
230 }
231
Corentin Wallez1f6c8c42019-10-23 11:57:41 +0000232 wgpu::TextureFormat resolveTargetFormat = resolveTarget->GetFormat().format;
Corentin Walleza838c7d2019-09-20 22:59:47 +0000233 if (resolveTargetFormat != attachment->GetFormat().format) {
Jiawei Shao1e1c13e2019-03-11 18:41:02 +0000234 return DAWN_VALIDATION_ERROR(
235 "The format of the resolve target must be the same as the color attachment");
236 }
237
238 return {};
239 }
240
Jiawei Shaob2c50232019-02-27 09:21:56 +0000241 MaybeError ValidateRenderPassColorAttachment(
242 const DeviceBase* device,
Corentin Walleza838c7d2019-09-20 22:59:47 +0000243 const RenderPassColorAttachmentDescriptor& colorAttachment,
Jiawei Shaob2c50232019-02-27 09:21:56 +0000244 uint32_t* width,
Jiawei Shao1e1c13e2019-03-11 18:41:02 +0000245 uint32_t* height,
246 uint32_t* sampleCount) {
Corentin Walleza838c7d2019-09-20 22:59:47 +0000247 DAWN_TRY(device->ValidateObject(colorAttachment.attachment));
Jiawei Shaob2c50232019-02-27 09:21:56 +0000248
Corentin Walleza838c7d2019-09-20 22:59:47 +0000249 const TextureViewBase* attachment = colorAttachment.attachment;
Corentin Walleza92f83b2019-06-21 10:16:15 +0000250 if (!attachment->GetFormat().IsColor() || !attachment->GetFormat().isRenderable) {
Jiawei Shaob2c50232019-02-27 09:21:56 +0000251 return DAWN_VALIDATION_ERROR(
252 "The format of the texture view used as color attachment is not color "
253 "renderable");
254 }
255
Jiawei Shao51c347a2019-12-12 01:29:01 +0000256 DAWN_TRY(ValidateLoadOp(colorAttachment.loadOp));
257 DAWN_TRY(ValidateStoreOp(colorAttachment.storeOp));
258
259 if (colorAttachment.loadOp == wgpu::LoadOp::Clear) {
260 if (std::isnan(colorAttachment.clearColor.r) ||
261 std::isnan(colorAttachment.clearColor.g) ||
262 std::isnan(colorAttachment.clearColor.b) ||
263 std::isnan(colorAttachment.clearColor.a)) {
264 return DAWN_VALIDATION_ERROR("Color clear value cannot contain NaN");
265 }
266 }
267
Jiawei Shao1e1c13e2019-03-11 18:41:02 +0000268 DAWN_TRY(ValidateOrSetColorAttachmentSampleCount(attachment, sampleCount));
269
270 DAWN_TRY(ValidateResolveTarget(device, colorAttachment));
271
Jiawei Shaob2c50232019-02-27 09:21:56 +0000272 DAWN_TRY(ValidateAttachmentArrayLayersAndLevelCount(attachment));
273 DAWN_TRY(ValidateOrSetAttachmentSize(attachment, width, height));
274
275 return {};
276 }
277
278 MaybeError ValidateRenderPassDepthStencilAttachment(
279 const DeviceBase* device,
280 const RenderPassDepthStencilAttachmentDescriptor* depthStencilAttachment,
281 uint32_t* width,
Jiawei Shao93131172019-03-15 05:16:41 +0000282 uint32_t* height,
283 uint32_t* sampleCount) {
Jiawei Shaob2c50232019-02-27 09:21:56 +0000284 DAWN_ASSERT(depthStencilAttachment != nullptr);
285
286 DAWN_TRY(device->ValidateObject(depthStencilAttachment->attachment));
287
288 const TextureViewBase* attachment = depthStencilAttachment->attachment;
Corentin Walleza92f83b2019-06-21 10:16:15 +0000289 if (!attachment->GetFormat().HasDepthOrStencil() ||
290 !attachment->GetFormat().isRenderable) {
Jiawei Shaob2c50232019-02-27 09:21:56 +0000291 return DAWN_VALIDATION_ERROR(
292 "The format of the texture view used as depth stencil attachment is not a "
293 "depth stencil format");
294 }
295
Jiawei Shao51c347a2019-12-12 01:29:01 +0000296 DAWN_TRY(ValidateLoadOp(depthStencilAttachment->depthLoadOp));
297 DAWN_TRY(ValidateLoadOp(depthStencilAttachment->stencilLoadOp));
298 DAWN_TRY(ValidateStoreOp(depthStencilAttachment->depthStoreOp));
299 DAWN_TRY(ValidateStoreOp(depthStencilAttachment->stencilStoreOp));
300
Brandon Jones7695afc2020-07-10 23:13:58 +0000301 if (attachment->GetAspect() == wgpu::TextureAspect::All &&
302 attachment->GetFormat().HasStencil() &&
303 depthStencilAttachment->depthReadOnly != depthStencilAttachment->stencilReadOnly) {
304 return DAWN_VALIDATION_ERROR(
305 "depthReadOnly and stencilReadOnly must be the same when texture aspect is "
306 "'all'");
307 }
308
309 if (depthStencilAttachment->depthReadOnly &&
310 (depthStencilAttachment->depthLoadOp != wgpu::LoadOp::Load ||
311 depthStencilAttachment->depthStoreOp != wgpu::StoreOp::Store)) {
312 return DAWN_VALIDATION_ERROR(
313 "depthLoadOp must be load and depthStoreOp must be store when depthReadOnly "
314 "is true.");
315 }
316
317 if (depthStencilAttachment->stencilReadOnly &&
318 (depthStencilAttachment->stencilLoadOp != wgpu::LoadOp::Load ||
319 depthStencilAttachment->stencilStoreOp != wgpu::StoreOp::Store)) {
320 return DAWN_VALIDATION_ERROR(
321 "stencilLoadOp must be load and stencilStoreOp must be store when "
322 "stencilReadOnly "
323 "is true.");
324 }
325
Jiawei Shao51c347a2019-12-12 01:29:01 +0000326 if (depthStencilAttachment->depthLoadOp == wgpu::LoadOp::Clear &&
327 std::isnan(depthStencilAttachment->clearDepth)) {
328 return DAWN_VALIDATION_ERROR("Depth clear value cannot be NaN");
329 }
330
Natasha Leecf0e9d92019-09-25 13:08:28 +0000331 // This validates that the depth storeOp and stencil storeOps are the same
332 if (depthStencilAttachment->depthStoreOp != depthStencilAttachment->stencilStoreOp) {
333 return DAWN_VALIDATION_ERROR(
334 "The depth storeOp and stencil storeOp are not the same");
335 }
336
Jiawei Shao93131172019-03-15 05:16:41 +0000337 // *sampleCount == 0 must only happen when there is no color attachment. In that case we
338 // do not need to validate the sample count of the depth stencil attachment.
Jiawei Shao54e4d472019-03-19 01:12:01 +0000339 const uint32_t depthStencilSampleCount = attachment->GetTexture()->GetSampleCount();
340 if (*sampleCount != 0) {
341 if (depthStencilSampleCount != *sampleCount) {
342 return DAWN_VALIDATION_ERROR("Depth stencil attachment sample counts mismatch");
343 }
344 } else {
345 *sampleCount = depthStencilSampleCount;
Jiawei Shao93131172019-03-15 05:16:41 +0000346 }
347
Jiawei Shaob2c50232019-02-27 09:21:56 +0000348 DAWN_TRY(ValidateAttachmentArrayLayersAndLevelCount(attachment));
349 DAWN_TRY(ValidateOrSetAttachmentSize(attachment, width, height));
350
351 return {};
352 }
353
Jiawei Shao54e4d472019-03-19 01:12:01 +0000354 MaybeError ValidateRenderPassDescriptor(const DeviceBase* device,
Corentin Wallez4b90c472019-07-10 20:43:13 +0000355 const RenderPassDescriptor* descriptor,
Jiawei Shao54e4d472019-03-19 01:12:01 +0000356 uint32_t* width,
357 uint32_t* height,
358 uint32_t* sampleCount) {
Corentin Wallez4b90c472019-07-10 20:43:13 +0000359 if (descriptor->colorAttachmentCount > kMaxColorAttachments) {
Jiawei Shaob2c50232019-02-27 09:21:56 +0000360 return DAWN_VALIDATION_ERROR("Setting color attachments out of bounds");
361 }
362
Corentin Wallez4b90c472019-07-10 20:43:13 +0000363 for (uint32_t i = 0; i < descriptor->colorAttachmentCount; ++i) {
364 DAWN_TRY(ValidateRenderPassColorAttachment(device, descriptor->colorAttachments[i],
Jiawei Shao54e4d472019-03-19 01:12:01 +0000365 width, height, sampleCount));
Jiawei Shaob2c50232019-02-27 09:21:56 +0000366 }
367
Corentin Wallez4b90c472019-07-10 20:43:13 +0000368 if (descriptor->depthStencilAttachment != nullptr) {
Jiawei Shaob2c50232019-02-27 09:21:56 +0000369 DAWN_TRY(ValidateRenderPassDepthStencilAttachment(
Corentin Wallez4b90c472019-07-10 20:43:13 +0000370 device, descriptor->depthStencilAttachment, width, height, sampleCount));
Jiawei Shaob2c50232019-02-27 09:21:56 +0000371 }
372
Kai Ninomiya53405b52020-07-11 03:15:16 +0000373 if (descriptor->occlusionQuerySet != nullptr) {
374 return DAWN_VALIDATION_ERROR("occlusionQuerySet not implemented");
375 }
376
Corentin Wallez4b90c472019-07-10 20:43:13 +0000377 if (descriptor->colorAttachmentCount == 0 &&
378 descriptor->depthStencilAttachment == nullptr) {
Jiawei Shaob2c50232019-02-27 09:21:56 +0000379 return DAWN_VALIDATION_ERROR("Cannot use render pass with no attachments.");
380 }
381
382 return {};
383 }
384
Corentin Wallez4b90c472019-07-10 20:43:13 +0000385 MaybeError ValidateComputePassDescriptor(const DeviceBase* device,
386 const ComputePassDescriptor* descriptor) {
387 return {};
388 }
389
Corentin Wallez984493d2020-06-16 03:05:17 +0000390 ResultOrError<TextureCopyView> FixTextureCopyView(DeviceBase* device,
391 const TextureCopyView* view) {
392 TextureCopyView fixedView = *view;
393
394 if (view->arrayLayer != 0) {
395 if (view->origin.z != 0) {
396 return DAWN_VALIDATION_ERROR("arrayLayer and origin.z cannot both be != 0");
397 } else {
398 fixedView.origin.z = fixedView.arrayLayer;
399 fixedView.arrayLayer = 1;
400 device->EmitDeprecationWarning(
401 "wgpu::TextureCopyView::arrayLayer is deprecated in favor of "
402 "::origin::z");
403 }
404 }
405
406 return fixedView;
407 }
408
Corentin Wallezf20f5b92019-02-20 11:46:16 +0000409 } // namespace
410
Corentin Wallez321c1222019-11-13 17:00:37 +0000411 CommandEncoder::CommandEncoder(DeviceBase* device, const CommandEncoderDescriptor*)
Austin Engfde94902019-07-24 18:15:24 +0000412 : ObjectBase(device), mEncodingContext(device, this) {
Corentin Wallezf20f5b92019-02-20 11:46:16 +0000413 }
414
Corentin Wallez321c1222019-11-13 17:00:37 +0000415 CommandBufferResourceUsage CommandEncoder::AcquireResourceUsages() {
Austin Eng4b0b7a52019-11-21 22:09:41 +0000416 return CommandBufferResourceUsage{mEncodingContext.AcquirePassUsages(),
Hao Li5191adc2020-07-01 10:48:16 +0000417 std::move(mTopLevelBuffers), std::move(mTopLevelTextures),
418 std::move(mUsedQuerySets)};
Corentin Wallezf20f5b92019-02-20 11:46:16 +0000419 }
420
Corentin Wallez321c1222019-11-13 17:00:37 +0000421 CommandIterator CommandEncoder::AcquireCommands() {
Austin Engfde94902019-07-24 18:15:24 +0000422 return mEncodingContext.AcquireCommands();
Corentin Wallezf20f5b92019-02-20 11:46:16 +0000423 }
424
Hao Li5191adc2020-07-01 10:48:16 +0000425 void CommandEncoder::TrackUsedQuerySet(QuerySetBase* querySet) {
426 mUsedQuerySets.insert(querySet);
427 }
428
Corentin Wallezf20f5b92019-02-20 11:46:16 +0000429 // Implementation of the API's command recording methods
430
Corentin Wallez321c1222019-11-13 17:00:37 +0000431 ComputePassEncoder* CommandEncoder::BeginComputePass(const ComputePassDescriptor* descriptor) {
Jiawei Shaob47470d2019-03-05 01:02:47 +0000432 DeviceBase* device = GetDevice();
Austin Engfde94902019-07-24 18:15:24 +0000433
434 bool success =
435 mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
436 DAWN_TRY(ValidateComputePassDescriptor(device, descriptor));
437
438 allocator->Allocate<BeginComputePassCmd>(Command::BeginComputePass);
439
440 return {};
441 });
442
443 if (success) {
Corentin Wallez321c1222019-11-13 17:00:37 +0000444 ComputePassEncoder* passEncoder =
445 new ComputePassEncoder(device, this, &mEncodingContext);
Austin Engfde94902019-07-24 18:15:24 +0000446 mEncodingContext.EnterPass(passEncoder);
447 return passEncoder;
Corentin Wallezf20f5b92019-02-20 11:46:16 +0000448 }
449
Corentin Wallez321c1222019-11-13 17:00:37 +0000450 return ComputePassEncoder::MakeError(device, this, &mEncodingContext);
Corentin Walleze1f0d4e2019-02-15 12:54:08 +0000451 }
452
Corentin Wallez321c1222019-11-13 17:00:37 +0000453 RenderPassEncoder* CommandEncoder::BeginRenderPass(const RenderPassDescriptor* descriptor) {
Jiawei Shaob2c50232019-02-27 09:21:56 +0000454 DeviceBase* device = GetDevice();
455
Jiawei Shao64fcf392020-04-22 00:55:43 +0000456 PassResourceUsageTracker usageTracker(PassType::Render);
Austin Engfde94902019-07-24 18:15:24 +0000457 bool success =
458 mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
459 uint32_t width = 0;
460 uint32_t height = 0;
461 uint32_t sampleCount = 0;
462
463 DAWN_TRY(ValidateRenderPassDescriptor(device, descriptor, &width, &height,
464 &sampleCount));
465
466 ASSERT(width > 0 && height > 0 && sampleCount > 0);
467
468 BeginRenderPassCmd* cmd =
469 allocator->Allocate<BeginRenderPassCmd>(Command::BeginRenderPass);
470
Austin Engb98f0fa2019-07-26 19:08:18 +0000471 cmd->attachmentState = device->GetOrCreateAttachmentState(descriptor);
472
473 for (uint32_t i : IterateBitSet(cmd->attachmentState->GetColorAttachmentsMask())) {
Austin Eng4b0b7a52019-11-21 22:09:41 +0000474 TextureViewBase* view = descriptor->colorAttachments[i].attachment;
475 TextureViewBase* resolveTarget = descriptor->colorAttachments[i].resolveTarget;
476
477 cmd->colorAttachments[i].view = view;
478 cmd->colorAttachments[i].resolveTarget = resolveTarget;
Corentin Walleza838c7d2019-09-20 22:59:47 +0000479 cmd->colorAttachments[i].loadOp = descriptor->colorAttachments[i].loadOp;
480 cmd->colorAttachments[i].storeOp = descriptor->colorAttachments[i].storeOp;
Austin Engb98f0fa2019-07-26 19:08:18 +0000481 cmd->colorAttachments[i].clearColor =
Corentin Walleza838c7d2019-09-20 22:59:47 +0000482 descriptor->colorAttachments[i].clearColor;
Austin Eng4b0b7a52019-11-21 22:09:41 +0000483
Yunchao He23428ea2020-05-04 17:10:49 +0000484 usageTracker.TextureViewUsedAs(view, wgpu::TextureUsage::OutputAttachment);
Austin Eng4b0b7a52019-11-21 22:09:41 +0000485
486 if (resolveTarget != nullptr) {
Yunchao He23428ea2020-05-04 17:10:49 +0000487 usageTracker.TextureViewUsedAs(resolveTarget,
488 wgpu::TextureUsage::OutputAttachment);
Austin Eng4b0b7a52019-11-21 22:09:41 +0000489 }
Austin Engfde94902019-07-24 18:15:24 +0000490 }
491
Austin Engb98f0fa2019-07-26 19:08:18 +0000492 if (cmd->attachmentState->HasDepthStencilAttachment()) {
Austin Eng4b0b7a52019-11-21 22:09:41 +0000493 TextureViewBase* view = descriptor->depthStencilAttachment->attachment;
494
495 cmd->depthStencilAttachment.view = view;
Austin Engfde94902019-07-24 18:15:24 +0000496 cmd->depthStencilAttachment.clearDepth =
497 descriptor->depthStencilAttachment->clearDepth;
498 cmd->depthStencilAttachment.clearStencil =
499 descriptor->depthStencilAttachment->clearStencil;
500 cmd->depthStencilAttachment.depthLoadOp =
501 descriptor->depthStencilAttachment->depthLoadOp;
502 cmd->depthStencilAttachment.depthStoreOp =
503 descriptor->depthStencilAttachment->depthStoreOp;
504 cmd->depthStencilAttachment.stencilLoadOp =
505 descriptor->depthStencilAttachment->stencilLoadOp;
506 cmd->depthStencilAttachment.stencilStoreOp =
507 descriptor->depthStencilAttachment->stencilStoreOp;
Austin Eng4b0b7a52019-11-21 22:09:41 +0000508
Yunchao He23428ea2020-05-04 17:10:49 +0000509 usageTracker.TextureViewUsedAs(view, wgpu::TextureUsage::OutputAttachment);
Austin Engfde94902019-07-24 18:15:24 +0000510 }
511
512 cmd->width = width;
513 cmd->height = height;
Austin Engfde94902019-07-24 18:15:24 +0000514
515 return {};
516 });
517
518 if (success) {
Austin Eng4b0b7a52019-11-21 22:09:41 +0000519 RenderPassEncoder* passEncoder =
520 new RenderPassEncoder(device, this, &mEncodingContext, std::move(usageTracker));
Austin Engfde94902019-07-24 18:15:24 +0000521 mEncodingContext.EnterPass(passEncoder);
522 return passEncoder;
Corentin Wallezf20f5b92019-02-20 11:46:16 +0000523 }
524
Corentin Wallez321c1222019-11-13 17:00:37 +0000525 return RenderPassEncoder::MakeError(device, this, &mEncodingContext);
Corentin Walleze1f0d4e2019-02-15 12:54:08 +0000526 }
527
Corentin Wallez321c1222019-11-13 17:00:37 +0000528 void CommandEncoder::CopyBufferToBuffer(BufferBase* source,
529 uint64_t sourceOffset,
530 BufferBase* destination,
531 uint64_t destinationOffset,
532 uint64_t size) {
Austin Engfde94902019-07-24 18:15:24 +0000533 mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
Corentin Wallezecf93472020-05-05 08:33:55 +0000534 if (GetDevice()->IsValidationEnabled()) {
535 DAWN_TRY(GetDevice()->ValidateObject(source));
536 DAWN_TRY(GetDevice()->ValidateObject(destination));
537
Jiawei Shao2ae84e92020-05-19 00:11:11 +0000538 if (source == destination) {
539 return DAWN_VALIDATION_ERROR(
540 "Source and destination cannot be the same buffer.");
541 }
542
Corentin Wallezecf93472020-05-05 08:33:55 +0000543 DAWN_TRY(ValidateCopySizeFitsInBuffer(source, sourceOffset, size));
544 DAWN_TRY(ValidateCopySizeFitsInBuffer(destination, destinationOffset, size));
545 DAWN_TRY(ValidateB2BCopyAlignment(size, sourceOffset, destinationOffset));
546
547 DAWN_TRY(ValidateCanUseAs(source, wgpu::BufferUsage::CopySrc));
548 DAWN_TRY(ValidateCanUseAs(destination, wgpu::BufferUsage::CopyDst));
549
550 mTopLevelBuffers.insert(source);
551 mTopLevelBuffers.insert(destination);
552 }
Corentin Wallezf20f5b92019-02-20 11:46:16 +0000553
Corentin Wallez90ad1a32020-06-11 11:23:35 +0000554 // Skip noop copies. Some backends validation rules disallow them.
555 if (size != 0) {
556 CopyBufferToBufferCmd* copy =
557 allocator->Allocate<CopyBufferToBufferCmd>(Command::CopyBufferToBuffer);
558 copy->source = source;
559 copy->sourceOffset = sourceOffset;
560 copy->destination = destination;
561 copy->destinationOffset = destinationOffset;
562 copy->size = size;
563 }
Corentin Wallezf20f5b92019-02-20 11:46:16 +0000564
Austin Engfde94902019-07-24 18:15:24 +0000565 return {};
566 });
Corentin Walleze1f0d4e2019-02-15 12:54:08 +0000567 }
568
Corentin Wallez321c1222019-11-13 17:00:37 +0000569 void CommandEncoder::CopyBufferToTexture(const BufferCopyView* source,
570 const TextureCopyView* destination,
571 const Extent3D* copySize) {
Austin Engfde94902019-07-24 18:15:24 +0000572 mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
Corentin Wallez984493d2020-06-16 03:05:17 +0000573 // TODO(dawn:22): Remove once migration from GPUTextureCopyView.arrayLayer to
574 // GPUTextureCopyView.origin.z is done.
575 TextureCopyView fixedDest;
576 DAWN_TRY_ASSIGN(fixedDest, FixTextureCopyView(GetDevice(), destination));
577 destination = &fixedDest;
578
Corentin Wallezecf93472020-05-05 08:33:55 +0000579 if (GetDevice()->IsValidationEnabled()) {
Tomek Ponitka0f5d4962020-07-07 10:18:51 +0000580 DAWN_TRY(ValidateBufferCopyView(GetDevice(), *source));
581 DAWN_TRY(ValidateCanUseAs(source->buffer, wgpu::BufferUsage::CopySrc));
582
583 DAWN_TRY(ValidateTextureCopyView(GetDevice(), *destination));
584 DAWN_TRY(ValidateCanUseAs(destination->texture, wgpu::TextureUsage::CopyDst));
585 DAWN_TRY(ValidateTextureSampleCountInCopyCommands(destination->texture));
586
587 TextureDataLayout sourceAsTextureDataLayout;
588 sourceAsTextureDataLayout.offset = source->offset;
589 sourceAsTextureDataLayout.bytesPerRow = source->bytesPerRow;
590 sourceAsTextureDataLayout.rowsPerImage = source->rowsPerImage;
591
592 DAWN_TRY(ValidateLinearTextureData(sourceAsTextureDataLayout,
593 source->buffer->GetSize(),
594 destination->texture->GetFormat(), *copySize));
595 DAWN_TRY(ValidateTextureCopyRange(*destination, *copySize));
596
597 mTopLevelBuffers.insert(source->buffer);
598 mTopLevelTextures.insert(destination->texture);
Corentin Wallezecf93472020-05-05 08:33:55 +0000599 }
Corentin Wallezf20f5b92019-02-20 11:46:16 +0000600
Corentin Walleze4f8e192020-05-29 07:28:38 +0000601 // Compute default value for rowsPerImage
Corentin Wallezecabfe82020-05-13 17:26:05 +0000602 uint32_t defaultedRowsPerImage = source->rowsPerImage;
Corentin Wallezecf93472020-05-05 08:33:55 +0000603 if (defaultedRowsPerImage == 0) {
604 defaultedRowsPerImage = copySize->height;
605 }
606
Corentin Wallezecf93472020-05-05 08:33:55 +0000607 // Record the copy command.
Austin Engfde94902019-07-24 18:15:24 +0000608 CopyBufferToTextureCmd* copy =
609 allocator->Allocate<CopyBufferToTextureCmd>(Command::CopyBufferToTexture);
Corentin Wallezecabfe82020-05-13 17:26:05 +0000610 copy->source.buffer = source->buffer;
611 copy->source.offset = source->offset;
Corentin Walleze4f8e192020-05-29 07:28:38 +0000612 copy->source.bytesPerRow = source->bytesPerRow;
Corentin Wallezecf93472020-05-05 08:33:55 +0000613 copy->source.rowsPerImage = defaultedRowsPerImage;
Austin Engfde94902019-07-24 18:15:24 +0000614 copy->destination.texture = destination->texture;
615 copy->destination.origin = destination->origin;
Austin Engfde94902019-07-24 18:15:24 +0000616 copy->destination.mipLevel = destination->mipLevel;
Corentin Wallezff905992020-06-26 11:07:00 +0000617 copy->copySize = *copySize;
Corentin Wallez984493d2020-06-16 03:05:17 +0000618
Austin Engfde94902019-07-24 18:15:24 +0000619 return {};
620 });
Corentin Walleze1f0d4e2019-02-15 12:54:08 +0000621 }
622
Corentin Wallez321c1222019-11-13 17:00:37 +0000623 void CommandEncoder::CopyTextureToBuffer(const TextureCopyView* source,
624 const BufferCopyView* destination,
625 const Extent3D* copySize) {
Austin Engfde94902019-07-24 18:15:24 +0000626 mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
Corentin Wallez984493d2020-06-16 03:05:17 +0000627 // TODO(dawn:22): Remove once migration from GPUTextureCopyView.arrayLayer to
628 // GPUTextureCopyView.origin.z is done.
629 TextureCopyView fixedSrc;
630 DAWN_TRY_ASSIGN(fixedSrc, FixTextureCopyView(GetDevice(), source));
631 source = &fixedSrc;
632
Corentin Wallezecf93472020-05-05 08:33:55 +0000633 if (GetDevice()->IsValidationEnabled()) {
Tomek Ponitka0f5d4962020-07-07 10:18:51 +0000634 DAWN_TRY(ValidateTextureCopyView(GetDevice(), *source));
635 DAWN_TRY(ValidateCanUseAs(source->texture, wgpu::TextureUsage::CopySrc));
636 DAWN_TRY(ValidateTextureSampleCountInCopyCommands(source->texture));
637
638 DAWN_TRY(ValidateBufferCopyView(GetDevice(), *destination));
639 DAWN_TRY(ValidateCanUseAs(destination->buffer, wgpu::BufferUsage::CopyDst));
640
641 TextureDataLayout dstAsTextureDataLayout;
642 dstAsTextureDataLayout.offset = destination->offset;
643 dstAsTextureDataLayout.bytesPerRow = destination->bytesPerRow;
644 dstAsTextureDataLayout.rowsPerImage = destination->rowsPerImage;
645
646 DAWN_TRY(ValidateLinearTextureData(dstAsTextureDataLayout,
647 destination->buffer->GetSize(),
648 source->texture->GetFormat(), *copySize));
649 DAWN_TRY(ValidateTextureCopyRange(*source, *copySize));
650
651 mTopLevelTextures.insert(source->texture);
652 mTopLevelBuffers.insert(destination->buffer);
Corentin Wallezecf93472020-05-05 08:33:55 +0000653 }
Corentin Wallezf20f5b92019-02-20 11:46:16 +0000654
Corentin Walleze4f8e192020-05-29 07:28:38 +0000655 // Compute default value for rowsPerImage
Corentin Wallezecabfe82020-05-13 17:26:05 +0000656 uint32_t defaultedRowsPerImage = destination->rowsPerImage;
Corentin Wallezecf93472020-05-05 08:33:55 +0000657 if (defaultedRowsPerImage == 0) {
658 defaultedRowsPerImage = copySize->height;
659 }
660
Corentin Wallezecf93472020-05-05 08:33:55 +0000661 // Record the copy command.
Austin Engfde94902019-07-24 18:15:24 +0000662 CopyTextureToBufferCmd* copy =
663 allocator->Allocate<CopyTextureToBufferCmd>(Command::CopyTextureToBuffer);
664 copy->source.texture = source->texture;
665 copy->source.origin = source->origin;
Austin Engfde94902019-07-24 18:15:24 +0000666 copy->source.mipLevel = source->mipLevel;
Corentin Wallezecabfe82020-05-13 17:26:05 +0000667 copy->destination.buffer = destination->buffer;
668 copy->destination.offset = destination->offset;
Corentin Walleze4f8e192020-05-29 07:28:38 +0000669 copy->destination.bytesPerRow = destination->bytesPerRow;
Corentin Wallezecf93472020-05-05 08:33:55 +0000670 copy->destination.rowsPerImage = defaultedRowsPerImage;
Corentin Wallezff905992020-06-26 11:07:00 +0000671 copy->copySize = *copySize;
Corentin Wallez984493d2020-06-16 03:05:17 +0000672
Austin Engfde94902019-07-24 18:15:24 +0000673 return {};
674 });
Corentin Walleze1f0d4e2019-02-15 12:54:08 +0000675 }
676
Corentin Wallez321c1222019-11-13 17:00:37 +0000677 void CommandEncoder::CopyTextureToTexture(const TextureCopyView* source,
678 const TextureCopyView* destination,
679 const Extent3D* copySize) {
Austin Engfde94902019-07-24 18:15:24 +0000680 mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
Corentin Wallez984493d2020-06-16 03:05:17 +0000681 // TODO(dawn:22): Remove once migration from GPUTextureCopyView.arrayLayer to
682 // GPUTextureCopyView.origin.z is done.
683 TextureCopyView fixedSrc;
684 DAWN_TRY_ASSIGN(fixedSrc, FixTextureCopyView(GetDevice(), source));
685 source = &fixedSrc;
686 TextureCopyView fixedDest;
687 DAWN_TRY_ASSIGN(fixedDest, FixTextureCopyView(GetDevice(), destination));
688 destination = &fixedDest;
689
Corentin Wallezecf93472020-05-05 08:33:55 +0000690 if (GetDevice()->IsValidationEnabled()) {
691 DAWN_TRY(GetDevice()->ValidateObject(source->texture));
692 DAWN_TRY(GetDevice()->ValidateObject(destination->texture));
693
694 DAWN_TRY(
695 ValidateTextureToTextureCopyRestrictions(*source, *destination, *copySize));
696
Tomek Ponitka0f5d4962020-07-07 10:18:51 +0000697 DAWN_TRY(ValidateTextureCopyRange(*source, *copySize));
698 DAWN_TRY(ValidateTextureCopyRange(*destination, *copySize));
Corentin Wallezecf93472020-05-05 08:33:55 +0000699
Tomek Ponitka0f5d4962020-07-07 10:18:51 +0000700 DAWN_TRY(ValidateTextureCopyView(GetDevice(), *source));
701 DAWN_TRY(ValidateTextureCopyView(GetDevice(), *destination));
Corentin Wallezecf93472020-05-05 08:33:55 +0000702
703 DAWN_TRY(ValidateCanUseAs(source->texture, wgpu::TextureUsage::CopySrc));
704 DAWN_TRY(ValidateCanUseAs(destination->texture, wgpu::TextureUsage::CopyDst));
705
706 mTopLevelTextures.insert(source->texture);
707 mTopLevelTextures.insert(destination->texture);
708 }
Brandon Jonesd3d3aa02019-03-26 11:06:23 +0000709
Austin Engfde94902019-07-24 18:15:24 +0000710 CopyTextureToTextureCmd* copy =
711 allocator->Allocate<CopyTextureToTextureCmd>(Command::CopyTextureToTexture);
712 copy->source.texture = source->texture;
713 copy->source.origin = source->origin;
714 copy->source.mipLevel = source->mipLevel;
Austin Engfde94902019-07-24 18:15:24 +0000715 copy->destination.texture = destination->texture;
716 copy->destination.origin = destination->origin;
717 copy->destination.mipLevel = destination->mipLevel;
Austin Engfde94902019-07-24 18:15:24 +0000718 copy->copySize = *copySize;
Brandon Jonesd3d3aa02019-03-26 11:06:23 +0000719
Austin Engfde94902019-07-24 18:15:24 +0000720 return {};
721 });
Brandon Jonesd3d3aa02019-03-26 11:06:23 +0000722 }
723
Corentin Wallez321c1222019-11-13 17:00:37 +0000724 void CommandEncoder::InsertDebugMarker(const char* groupLabel) {
Corentin Wallezb8ea84c2019-09-10 08:20:40 +0000725 mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
726 InsertDebugMarkerCmd* cmd =
727 allocator->Allocate<InsertDebugMarkerCmd>(Command::InsertDebugMarker);
728 cmd->length = strlen(groupLabel);
729
730 char* label = allocator->AllocateData<char>(cmd->length + 1);
731 memcpy(label, groupLabel, cmd->length + 1);
732
733 return {};
734 });
735 }
736
Corentin Wallez321c1222019-11-13 17:00:37 +0000737 void CommandEncoder::PopDebugGroup() {
Corentin Wallezb8ea84c2019-09-10 08:20:40 +0000738 mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
739 allocator->Allocate<PopDebugGroupCmd>(Command::PopDebugGroup);
740
741 return {};
742 });
743 }
744
Corentin Wallez321c1222019-11-13 17:00:37 +0000745 void CommandEncoder::PushDebugGroup(const char* groupLabel) {
Corentin Wallezb8ea84c2019-09-10 08:20:40 +0000746 mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
747 PushDebugGroupCmd* cmd =
748 allocator->Allocate<PushDebugGroupCmd>(Command::PushDebugGroup);
749 cmd->length = strlen(groupLabel);
750
751 char* label = allocator->AllocateData<char>(cmd->length + 1);
752 memcpy(label, groupLabel, cmd->length + 1);
753
754 return {};
755 });
756 }
757
Hao Li5191adc2020-07-01 10:48:16 +0000758 void CommandEncoder::WriteTimestamp(QuerySetBase* querySet, uint32_t queryIndex) {
759 mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
760 if (GetDevice()->IsValidationEnabled()) {
761 DAWN_TRY(GetDevice()->ValidateObject(querySet));
762 DAWN_TRY(ValidateTimestampQuery(querySet, queryIndex));
763 TrackUsedQuerySet(querySet);
764 }
765
766 WriteTimestampCmd* cmd =
767 allocator->Allocate<WriteTimestampCmd>(Command::WriteTimestamp);
768 cmd->querySet = querySet;
769 cmd->queryIndex = queryIndex;
770
771 return {};
772 });
773 }
774
Corentin Wallez321c1222019-11-13 17:00:37 +0000775 CommandBufferBase* CommandEncoder::Finish(const CommandBufferDescriptor* descriptor) {
Austin Eng4b0b7a52019-11-21 22:09:41 +0000776 DeviceBase* device = GetDevice();
777 // Even if mEncodingContext.Finish() validation fails, calling it will mutate the internal
778 // state of the encoding context. The internal state is set to finished, and subsequent
779 // calls to encode commands will generate errors.
780 if (device->ConsumedError(mEncodingContext.Finish()) ||
Natasha Lee2dd9ed02020-01-31 19:26:49 +0000781 device->ConsumedError(device->ValidateIsAlive()) ||
Austin Eng4b0b7a52019-11-21 22:09:41 +0000782 (device->IsValidationEnabled() &&
783 device->ConsumedError(ValidateFinish(mEncodingContext.GetIterator(),
784 mEncodingContext.GetPassUsages())))) {
785 return CommandBufferBase::MakeError(device);
Corentin Walleze1f0d4e2019-02-15 12:54:08 +0000786 }
787 ASSERT(!IsError());
Austin Eng4b0b7a52019-11-21 22:09:41 +0000788 return device->CreateCommandBuffer(this, descriptor);
Corentin Walleze1f0d4e2019-02-15 12:54:08 +0000789 }
790
Corentin Wallezf20f5b92019-02-20 11:46:16 +0000791 // Implementation of the command buffer validation that can be precomputed before submit
Austin Eng4b0b7a52019-11-21 22:09:41 +0000792 MaybeError CommandEncoder::ValidateFinish(CommandIterator* commands,
793 const PerPassUsages& perPassUsages) const {
Corentin Wallez321c1222019-11-13 17:00:37 +0000794 TRACE_EVENT0(GetDevice()->GetPlatform(), Validation, "CommandEncoder::ValidateFinish");
Corentin Walleze1f0d4e2019-02-15 12:54:08 +0000795 DAWN_TRY(GetDevice()->ValidateObject(this));
Corentin Wallezf20f5b92019-02-20 11:46:16 +0000796
Austin Eng4b0b7a52019-11-21 22:09:41 +0000797 for (const PassResourceUsage& passUsage : perPassUsages) {
798 DAWN_TRY(ValidatePassResourceUsage(passUsage));
799 }
Corentin Wallezf20f5b92019-02-20 11:46:16 +0000800
Corentin Wallezb8ea84c2019-09-10 08:20:40 +0000801 uint64_t debugGroupStackSize = 0;
802
Austin Engfde94902019-07-24 18:15:24 +0000803 commands->Reset();
Corentin Wallezf20f5b92019-02-20 11:46:16 +0000804 Command type;
Austin Engfde94902019-07-24 18:15:24 +0000805 while (commands->NextCommandId(&type)) {
Corentin Wallezf20f5b92019-02-20 11:46:16 +0000806 switch (type) {
807 case Command::BeginComputePass: {
Austin Engfde94902019-07-24 18:15:24 +0000808 commands->NextCommand<BeginComputePassCmd>();
Austin Eng4b0b7a52019-11-21 22:09:41 +0000809 DAWN_TRY(ValidateComputePass(commands));
Corentin Walleze8316532020-04-02 16:45:17 +0000810 break;
811 }
Corentin Wallezf20f5b92019-02-20 11:46:16 +0000812
813 case Command::BeginRenderPass: {
Austin Eng4b0b7a52019-11-21 22:09:41 +0000814 const BeginRenderPassCmd* cmd = commands->NextCommand<BeginRenderPassCmd>();
815 DAWN_TRY(ValidateRenderPass(commands, cmd));
Corentin Walleze8316532020-04-02 16:45:17 +0000816 break;
817 }
Corentin Wallezf20f5b92019-02-20 11:46:16 +0000818
819 case Command::CopyBufferToBuffer: {
Corentin Wallezecf93472020-05-05 08:33:55 +0000820 commands->NextCommand<CopyBufferToBufferCmd>();
Corentin Walleze8316532020-04-02 16:45:17 +0000821 break;
822 }
Corentin Wallezf20f5b92019-02-20 11:46:16 +0000823
824 case Command::CopyBufferToTexture: {
Corentin Wallezecf93472020-05-05 08:33:55 +0000825 commands->NextCommand<CopyBufferToTextureCmd>();
Corentin Walleze8316532020-04-02 16:45:17 +0000826 break;
827 }
Corentin Wallezf20f5b92019-02-20 11:46:16 +0000828
829 case Command::CopyTextureToBuffer: {
Corentin Wallezecf93472020-05-05 08:33:55 +0000830 commands->NextCommand<CopyTextureToBufferCmd>();
Corentin Walleze8316532020-04-02 16:45:17 +0000831 break;
832 }
Corentin Wallezf20f5b92019-02-20 11:46:16 +0000833
Brandon Jonesd3d3aa02019-03-26 11:06:23 +0000834 case Command::CopyTextureToTexture: {
Corentin Wallezecf93472020-05-05 08:33:55 +0000835 commands->NextCommand<CopyTextureToTextureCmd>();
Corentin Walleze8316532020-04-02 16:45:17 +0000836 break;
837 }
Brandon Jonesd3d3aa02019-03-26 11:06:23 +0000838
Corentin Wallezb8ea84c2019-09-10 08:20:40 +0000839 case Command::InsertDebugMarker: {
Austin Eng4b0b7a52019-11-21 22:09:41 +0000840 const InsertDebugMarkerCmd* cmd = commands->NextCommand<InsertDebugMarkerCmd>();
Corentin Wallezb8ea84c2019-09-10 08:20:40 +0000841 commands->NextData<char>(cmd->length + 1);
Corentin Walleze8316532020-04-02 16:45:17 +0000842 break;
843 }
Corentin Wallezb8ea84c2019-09-10 08:20:40 +0000844
845 case Command::PopDebugGroup: {
846 commands->NextCommand<PopDebugGroupCmd>();
847 DAWN_TRY(ValidateCanPopDebugGroup(debugGroupStackSize));
848 debugGroupStackSize--;
Corentin Walleze8316532020-04-02 16:45:17 +0000849 break;
850 }
Corentin Wallezb8ea84c2019-09-10 08:20:40 +0000851
852 case Command::PushDebugGroup: {
Austin Eng4b0b7a52019-11-21 22:09:41 +0000853 const PushDebugGroupCmd* cmd = commands->NextCommand<PushDebugGroupCmd>();
Corentin Wallezb8ea84c2019-09-10 08:20:40 +0000854 commands->NextData<char>(cmd->length + 1);
855 debugGroupStackSize++;
Corentin Walleze8316532020-04-02 16:45:17 +0000856 break;
857 }
Hao Li5191adc2020-07-01 10:48:16 +0000858
859 case Command::WriteTimestamp: {
860 commands->NextCommand<WriteTimestampCmd>();
861 break;
862 }
Corentin Wallezf20f5b92019-02-20 11:46:16 +0000863 default:
864 return DAWN_VALIDATION_ERROR("Command disallowed outside of a pass");
865 }
866 }
867
Corentin Wallezb8ea84c2019-09-10 08:20:40 +0000868 DAWN_TRY(ValidateFinalDebugGroupStackSize(debugGroupStackSize));
869
Corentin Walleze1f0d4e2019-02-15 12:54:08 +0000870 return {};
871 }
872
Corentin Walleze1f0d4e2019-02-15 12:54:08 +0000873} // namespace dawn_native