• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 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/CommandBufferStateTracker.h"
16 
17 #include "common/Assert.h"
18 #include "common/BitSetIterator.h"
19 #include "dawn_native/BindGroup.h"
20 #include "dawn_native/ComputePipeline.h"
21 #include "dawn_native/Forward.h"
22 #include "dawn_native/PipelineLayout.h"
23 #include "dawn_native/RenderPipeline.h"
24 
25 namespace dawn_native {
26 
27     enum ValidationAspect {
28         VALIDATION_ASPECT_PIPELINE,
29         VALIDATION_ASPECT_BIND_GROUPS,
30         VALIDATION_ASPECT_VERTEX_BUFFERS,
31         VALIDATION_ASPECT_INDEX_BUFFER,
32 
33         VALIDATION_ASPECT_COUNT
34     };
35     static_assert(VALIDATION_ASPECT_COUNT == CommandBufferStateTracker::kNumAspects, "");
36 
37     static constexpr CommandBufferStateTracker::ValidationAspects kDispatchAspects =
38         1 << VALIDATION_ASPECT_PIPELINE | 1 << VALIDATION_ASPECT_BIND_GROUPS;
39 
40     static constexpr CommandBufferStateTracker::ValidationAspects kDrawAspects =
41         1 << VALIDATION_ASPECT_PIPELINE | 1 << VALIDATION_ASPECT_BIND_GROUPS |
42         1 << VALIDATION_ASPECT_VERTEX_BUFFERS;
43 
44     static constexpr CommandBufferStateTracker::ValidationAspects kDrawIndexedAspects =
45         1 << VALIDATION_ASPECT_PIPELINE | 1 << VALIDATION_ASPECT_BIND_GROUPS |
46         1 << VALIDATION_ASPECT_VERTEX_BUFFERS | 1 << VALIDATION_ASPECT_INDEX_BUFFER;
47 
48     static constexpr CommandBufferStateTracker::ValidationAspects kLazyAspects =
49         1 << VALIDATION_ASPECT_BIND_GROUPS | 1 << VALIDATION_ASPECT_VERTEX_BUFFERS;
50 
ValidateCanDispatch()51     MaybeError CommandBufferStateTracker::ValidateCanDispatch() {
52         return ValidateOperation(kDispatchAspects);
53     }
54 
ValidateCanDraw()55     MaybeError CommandBufferStateTracker::ValidateCanDraw() {
56         return ValidateOperation(kDrawAspects);
57     }
58 
ValidateCanDrawIndexed()59     MaybeError CommandBufferStateTracker::ValidateCanDrawIndexed() {
60         return ValidateOperation(kDrawIndexedAspects);
61     }
62 
ValidateOperation(ValidationAspects requiredAspects)63     MaybeError CommandBufferStateTracker::ValidateOperation(ValidationAspects requiredAspects) {
64         // Fast return-true path if everything is good
65         ValidationAspects missingAspects = requiredAspects & ~mAspects;
66         if (missingAspects.none()) {
67             return {};
68         }
69 
70         // Generate an error immediately if a non-lazy aspect is missing as computing lazy aspects
71         // requires the pipeline to be set.
72         if ((missingAspects & ~kLazyAspects).any()) {
73             return GenerateAspectError(missingAspects);
74         }
75 
76         RecomputeLazyAspects(missingAspects);
77 
78         missingAspects = requiredAspects & ~mAspects;
79         if (missingAspects.any()) {
80             return GenerateAspectError(missingAspects);
81         }
82 
83         return {};
84     }
85 
RecomputeLazyAspects(ValidationAspects aspects)86     void CommandBufferStateTracker::RecomputeLazyAspects(ValidationAspects aspects) {
87         ASSERT(mAspects[VALIDATION_ASPECT_PIPELINE]);
88         ASSERT((aspects & ~kLazyAspects).none());
89 
90         if (aspects[VALIDATION_ASPECT_BIND_GROUPS]) {
91             bool matches = true;
92 
93             for (uint32_t i : IterateBitSet(mLastPipelineLayout->GetBindGroupLayoutsMask())) {
94                 if (mBindgroups[i] == nullptr ||
95                     mLastPipelineLayout->GetBindGroupLayout(i) != mBindgroups[i]->GetLayout()) {
96                     matches = false;
97                     break;
98                 }
99             }
100 
101             if (matches) {
102                 mAspects.set(VALIDATION_ASPECT_BIND_GROUPS);
103             }
104         }
105 
106         if (aspects[VALIDATION_ASPECT_VERTEX_BUFFERS]) {
107             ASSERT(mLastRenderPipeline != nullptr);
108 
109             auto requiredInputs = mLastRenderPipeline->GetInputsSetMask();
110             if ((mInputsSet & requiredInputs) == requiredInputs) {
111                 mAspects.set(VALIDATION_ASPECT_VERTEX_BUFFERS);
112             }
113         }
114     }
115 
GenerateAspectError(ValidationAspects aspects)116     MaybeError CommandBufferStateTracker::GenerateAspectError(ValidationAspects aspects) {
117         ASSERT(aspects.any());
118 
119         if (aspects[VALIDATION_ASPECT_INDEX_BUFFER]) {
120             return DAWN_VALIDATION_ERROR("Missing index buffer");
121         }
122 
123         if (aspects[VALIDATION_ASPECT_VERTEX_BUFFERS]) {
124             return DAWN_VALIDATION_ERROR("Missing vertex buffer");
125         }
126 
127         if (aspects[VALIDATION_ASPECT_BIND_GROUPS]) {
128             return DAWN_VALIDATION_ERROR("Missing bind group");
129         }
130 
131         if (aspects[VALIDATION_ASPECT_PIPELINE]) {
132             return DAWN_VALIDATION_ERROR("Missing pipeline");
133         }
134 
135         UNREACHABLE();
136     }
137 
SetComputePipeline(ComputePipelineBase * pipeline)138     void CommandBufferStateTracker::SetComputePipeline(ComputePipelineBase* pipeline) {
139         SetPipelineCommon(pipeline);
140     }
141 
SetRenderPipeline(RenderPipelineBase * pipeline)142     void CommandBufferStateTracker::SetRenderPipeline(RenderPipelineBase* pipeline) {
143         mLastRenderPipeline = pipeline;
144         SetPipelineCommon(pipeline);
145     }
146 
SetBindGroup(uint32_t index,BindGroupBase * bindgroup)147     void CommandBufferStateTracker::SetBindGroup(uint32_t index, BindGroupBase* bindgroup) {
148         mBindgroups[index] = bindgroup;
149     }
150 
SetIndexBuffer()151     void CommandBufferStateTracker::SetIndexBuffer() {
152         mAspects.set(VALIDATION_ASPECT_INDEX_BUFFER);
153     }
154 
SetVertexBuffer(uint32_t start,uint32_t count)155     void CommandBufferStateTracker::SetVertexBuffer(uint32_t start, uint32_t count) {
156         for (uint32_t i = 0; i < count; ++i) {
157             mInputsSet.set(start + i);
158         }
159     }
160 
SetPipelineCommon(PipelineBase * pipeline)161     void CommandBufferStateTracker::SetPipelineCommon(PipelineBase* pipeline) {
162         mLastPipelineLayout = pipeline->GetLayout();
163 
164         mAspects.set(VALIDATION_ASPECT_PIPELINE);
165 
166         // Reset lazy aspects so they get recomputed on the next operation.
167         mAspects &= ~kLazyAspects;
168     }
169 
170 }  // namespace dawn_native
171