• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/RenderBundleEncoder.h"
16 
17 #include "dawn_native/CommandValidation.h"
18 #include "dawn_native/Commands.h"
19 #include "dawn_native/Device.h"
20 #include "dawn_native/Format.h"
21 #include "dawn_native/ObjectType_autogen.h"
22 #include "dawn_native/RenderPipeline.h"
23 #include "dawn_native/ValidationUtils_autogen.h"
24 #include "dawn_platform/DawnPlatform.h"
25 #include "dawn_platform/tracing/TraceEvent.h"
26 
27 namespace dawn_native {
28 
ValidateColorAttachmentFormat(const DeviceBase * device,wgpu::TextureFormat textureFormat)29     MaybeError ValidateColorAttachmentFormat(const DeviceBase* device,
30                                              wgpu::TextureFormat textureFormat) {
31         DAWN_TRY(ValidateTextureFormat(textureFormat));
32         const Format* format = nullptr;
33         DAWN_TRY_ASSIGN(format, device->GetInternalFormat(textureFormat));
34         DAWN_INVALID_IF(!format->IsColor() || !format->isRenderable,
35                         "Texture format %s is not color renderable.", textureFormat);
36         return {};
37     }
38 
ValidateDepthStencilAttachmentFormat(const DeviceBase * device,wgpu::TextureFormat textureFormat,bool depthReadOnly,bool stencilReadOnly)39     MaybeError ValidateDepthStencilAttachmentFormat(const DeviceBase* device,
40                                                     wgpu::TextureFormat textureFormat,
41                                                     bool depthReadOnly,
42                                                     bool stencilReadOnly) {
43         DAWN_TRY(ValidateTextureFormat(textureFormat));
44         const Format* format = nullptr;
45         DAWN_TRY_ASSIGN(format, device->GetInternalFormat(textureFormat));
46         DAWN_INVALID_IF(!format->HasDepthOrStencil() || !format->isRenderable,
47                         "Texture format %s is not depth/stencil renderable.", textureFormat);
48 
49         DAWN_INVALID_IF(
50             format->HasDepth() && format->HasStencil() && depthReadOnly != stencilReadOnly,
51             "depthReadOnly (%u) and stencilReadOnly (%u) must be the same when format %s has "
52             "both depth and stencil aspects.",
53             depthReadOnly, stencilReadOnly, textureFormat);
54 
55         return {};
56     }
57 
ValidateRenderBundleEncoderDescriptor(const DeviceBase * device,const RenderBundleEncoderDescriptor * descriptor)58     MaybeError ValidateRenderBundleEncoderDescriptor(
59         const DeviceBase* device,
60         const RenderBundleEncoderDescriptor* descriptor) {
61         DAWN_INVALID_IF(!IsValidSampleCount(descriptor->sampleCount),
62                         "Sample count (%u) is not supported.", descriptor->sampleCount);
63 
64         DAWN_INVALID_IF(
65             descriptor->colorFormatsCount > kMaxColorAttachments,
66             "Color formats count (%u) exceeds maximum number of color attachements (%u).",
67             descriptor->colorFormatsCount, kMaxColorAttachments);
68 
69         DAWN_INVALID_IF(descriptor->colorFormatsCount == 0 &&
70                             descriptor->depthStencilFormat == wgpu::TextureFormat::Undefined,
71                         "No color or depth/stencil attachment formats specified.");
72 
73         for (uint32_t i = 0; i < descriptor->colorFormatsCount; ++i) {
74             DAWN_TRY_CONTEXT(ValidateColorAttachmentFormat(device, descriptor->colorFormats[i]),
75                              "validating colorFormats[%u]", i);
76         }
77 
78         if (descriptor->depthStencilFormat != wgpu::TextureFormat::Undefined) {
79             DAWN_TRY_CONTEXT(ValidateDepthStencilAttachmentFormat(
80                                  device, descriptor->depthStencilFormat, descriptor->depthReadOnly,
81                                  descriptor->stencilReadOnly),
82                              "validating depthStencilFormat");
83         }
84 
85         return {};
86     }
87 
RenderBundleEncoder(DeviceBase * device,const RenderBundleEncoderDescriptor * descriptor)88     RenderBundleEncoder::RenderBundleEncoder(DeviceBase* device,
89                                              const RenderBundleEncoderDescriptor* descriptor)
90         : RenderEncoderBase(device,
91                             descriptor->label,
92                             &mBundleEncodingContext,
93                             device->GetOrCreateAttachmentState(descriptor),
94                             descriptor->depthReadOnly,
95                             descriptor->stencilReadOnly),
96           mBundleEncodingContext(device, this) {
97         TrackInDevice();
98     }
99 
RenderBundleEncoder(DeviceBase * device,ErrorTag errorTag)100     RenderBundleEncoder::RenderBundleEncoder(DeviceBase* device, ErrorTag errorTag)
101         : RenderEncoderBase(device, &mBundleEncodingContext, errorTag),
102           mBundleEncodingContext(device, this) {
103     }
104 
DestroyImpl()105     void RenderBundleEncoder::DestroyImpl() {
106         RenderEncoderBase::DestroyImpl();
107         mBundleEncodingContext.Destroy();
108     }
109 
110     // static
Create(DeviceBase * device,const RenderBundleEncoderDescriptor * descriptor)111     Ref<RenderBundleEncoder> RenderBundleEncoder::Create(
112         DeviceBase* device,
113         const RenderBundleEncoderDescriptor* descriptor) {
114         return AcquireRef(new RenderBundleEncoder(device, descriptor));
115     }
116 
117     // static
MakeError(DeviceBase * device)118     RenderBundleEncoder* RenderBundleEncoder::MakeError(DeviceBase* device) {
119         return new RenderBundleEncoder(device, ObjectBase::kError);
120     }
121 
GetType() const122     ObjectType RenderBundleEncoder::GetType() const {
123         return ObjectType::RenderBundleEncoder;
124     }
125 
AcquireCommands()126     CommandIterator RenderBundleEncoder::AcquireCommands() {
127         return mBundleEncodingContext.AcquireCommands();
128     }
129 
APIFinish(const RenderBundleDescriptor * descriptor)130     RenderBundleBase* RenderBundleEncoder::APIFinish(const RenderBundleDescriptor* descriptor) {
131         RenderBundleBase* result = nullptr;
132 
133         if (GetDevice()->ConsumedError(FinishImpl(descriptor), &result, "calling %s.Finish(%s).",
134                                        this, descriptor)) {
135             return RenderBundleBase::MakeError(GetDevice());
136         }
137 
138         return result;
139     }
140 
FinishImpl(const RenderBundleDescriptor * descriptor)141     ResultOrError<RenderBundleBase*> RenderBundleEncoder::FinishImpl(
142         const RenderBundleDescriptor* descriptor) {
143         // Even if mBundleEncodingContext.Finish() validation fails, calling it will mutate the
144         // internal state of the encoding context. Subsequent calls to encode commands will generate
145         // errors.
146         DAWN_TRY(mBundleEncodingContext.Finish());
147 
148         RenderPassResourceUsage usages = mUsageTracker.AcquireResourceUsage();
149         if (IsValidationEnabled()) {
150             DAWN_TRY(GetDevice()->ValidateObject(this));
151             DAWN_TRY(ValidateProgrammableEncoderEnd());
152             DAWN_TRY(ValidateFinish(usages));
153         }
154 
155         return new RenderBundleBase(this, descriptor, AcquireAttachmentState(), IsDepthReadOnly(),
156                                     IsStencilReadOnly(), std::move(usages),
157                                     std::move(mIndirectDrawMetadata));
158     }
159 
ValidateFinish(const RenderPassResourceUsage & usages) const160     MaybeError RenderBundleEncoder::ValidateFinish(const RenderPassResourceUsage& usages) const {
161         TRACE_EVENT0(GetDevice()->GetPlatform(), Validation, "RenderBundleEncoder::ValidateFinish");
162         DAWN_TRY(GetDevice()->ValidateObject(this));
163         DAWN_TRY(ValidateSyncScopeResourceUsage(usages));
164         return {};
165     }
166 
167 }  // namespace dawn_native
168