• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 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/ProgrammablePassEncoder.h"
16 
17 #include "dawn_native/BindGroup.h"
18 #include "dawn_native/Buffer.h"
19 #include "dawn_native/CommandBuffer.h"
20 #include "dawn_native/Commands.h"
21 #include "dawn_native/Device.h"
22 #include "dawn_native/ValidationUtils_autogen.h"
23 
24 #include <string.h>
25 
26 namespace dawn_native {
27 
ProgrammablePassEncoder(DeviceBase * device,CommandEncoderBase * topLevelEncoder,CommandAllocator * allocator)28     ProgrammablePassEncoder::ProgrammablePassEncoder(DeviceBase* device,
29                                                      CommandEncoderBase* topLevelEncoder,
30                                                      CommandAllocator* allocator)
31         : ObjectBase(device), mTopLevelEncoder(topLevelEncoder), mAllocator(allocator) {
32         DAWN_ASSERT(allocator != nullptr);
33     }
34 
ProgrammablePassEncoder(DeviceBase * device,CommandEncoderBase * topLevelEncoder,ErrorTag errorTag)35     ProgrammablePassEncoder::ProgrammablePassEncoder(DeviceBase* device,
36                                                      CommandEncoderBase* topLevelEncoder,
37                                                      ErrorTag errorTag)
38         : ObjectBase(device, errorTag), mTopLevelEncoder(topLevelEncoder), mAllocator(nullptr) {
39     }
40 
EndPass()41     void ProgrammablePassEncoder::EndPass() {
42         if (mTopLevelEncoder->ConsumedError(ValidateCanRecordCommands())) {
43             return;
44         }
45 
46         mTopLevelEncoder->PassEnded();
47         mAllocator = nullptr;
48     }
49 
InsertDebugMarker(const char * groupLabel)50     void ProgrammablePassEncoder::InsertDebugMarker(const char* groupLabel) {
51         if (mTopLevelEncoder->ConsumedError(ValidateCanRecordCommands())) {
52             return;
53         }
54 
55         InsertDebugMarkerCmd* cmd =
56             mAllocator->Allocate<InsertDebugMarkerCmd>(Command::InsertDebugMarker);
57         cmd->length = strlen(groupLabel);
58 
59         char* label = mAllocator->AllocateData<char>(cmd->length + 1);
60         memcpy(label, groupLabel, cmd->length + 1);
61     }
62 
PopDebugGroup()63     void ProgrammablePassEncoder::PopDebugGroup() {
64         if (mTopLevelEncoder->ConsumedError(ValidateCanRecordCommands())) {
65             return;
66         }
67 
68         mAllocator->Allocate<PopDebugGroupCmd>(Command::PopDebugGroup);
69     }
70 
PushDebugGroup(const char * groupLabel)71     void ProgrammablePassEncoder::PushDebugGroup(const char* groupLabel) {
72         if (mTopLevelEncoder->ConsumedError(ValidateCanRecordCommands())) {
73             return;
74         }
75 
76         PushDebugGroupCmd* cmd = mAllocator->Allocate<PushDebugGroupCmd>(Command::PushDebugGroup);
77         cmd->length = strlen(groupLabel);
78 
79         char* label = mAllocator->AllocateData<char>(cmd->length + 1);
80         memcpy(label, groupLabel, cmd->length + 1);
81     }
82 
SetBindGroup(uint32_t groupIndex,BindGroupBase * group,uint32_t dynamicOffsetCount,const uint64_t * dynamicOffsets)83     void ProgrammablePassEncoder::SetBindGroup(uint32_t groupIndex,
84                                                BindGroupBase* group,
85                                                uint32_t dynamicOffsetCount,
86                                                const uint64_t* dynamicOffsets) {
87         const BindGroupLayoutBase* layout = group->GetLayout();
88 
89         if (mTopLevelEncoder->ConsumedError(ValidateCanRecordCommands()) ||
90             mTopLevelEncoder->ConsumedError(GetDevice()->ValidateObject(group))) {
91             return;
92         }
93 
94         if (groupIndex >= kMaxBindGroups) {
95             mTopLevelEncoder->HandleError("Setting bind group over the max");
96             return;
97         }
98 
99         // Dynamic offsets count must match the number required by the layout perfectly.
100         if (layout->GetDynamicBufferCount() != dynamicOffsetCount) {
101             mTopLevelEncoder->HandleError("dynamicOffset count mismatch");
102         }
103 
104         for (uint32_t i = 0; i < dynamicOffsetCount; ++i) {
105             if (dynamicOffsets[i] % kMinDynamicBufferOffsetAlignment != 0) {
106                 mTopLevelEncoder->HandleError("Dynamic Buffer Offset need to be aligned");
107                 return;
108             }
109 
110             BufferBinding bufferBinding = group->GetBindingAsBufferBinding(i);
111 
112             // During BindGroup creation, validation ensures binding offset + binding size <= buffer
113             // size.
114             DAWN_ASSERT(bufferBinding.buffer->GetSize() >= bufferBinding.size);
115             DAWN_ASSERT(bufferBinding.buffer->GetSize() - bufferBinding.size >=
116                         bufferBinding.offset);
117 
118             if (dynamicOffsets[i] >
119                 bufferBinding.buffer->GetSize() - bufferBinding.offset - bufferBinding.size) {
120                 mTopLevelEncoder->HandleError("dynamic offset out of bounds");
121                 return;
122             }
123         }
124 
125         SetBindGroupCmd* cmd = mAllocator->Allocate<SetBindGroupCmd>(Command::SetBindGroup);
126         cmd->index = groupIndex;
127         cmd->group = group;
128         cmd->dynamicOffsetCount = dynamicOffsetCount;
129         if (dynamicOffsetCount > 0) {
130             uint64_t* offsets = mAllocator->AllocateData<uint64_t>(cmd->dynamicOffsetCount);
131             memcpy(offsets, dynamicOffsets, dynamicOffsetCount * sizeof(uint64_t));
132         }
133     }
134 
ValidateCanRecordCommands() const135     MaybeError ProgrammablePassEncoder::ValidateCanRecordCommands() const {
136         if (mAllocator == nullptr) {
137             return DAWN_VALIDATION_ERROR("Recording in an error or already ended pass encoder");
138         }
139 
140         return nullptr;
141     }
142 
143 }  // namespace dawn_native
144