• 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_wire/client/Client.h"
16 
17 #include "common/Compiler.h"
18 #include "dawn_wire/client/Device.h"
19 
20 namespace dawn_wire { namespace client {
21 
22     namespace {
23 
24         class NoopCommandSerializer final : public CommandSerializer {
25           public:
GetInstance()26             static NoopCommandSerializer* GetInstance() {
27                 static NoopCommandSerializer gNoopCommandSerializer;
28                 return &gNoopCommandSerializer;
29             }
30 
31             ~NoopCommandSerializer() = default;
32 
GetMaximumAllocationSize() const33             size_t GetMaximumAllocationSize() const final {
34                 return 0;
35             }
GetCmdSpace(size_t size)36             void* GetCmdSpace(size_t size) final {
37                 return nullptr;
38             }
Flush()39             bool Flush() final {
40                 return false;
41             }
42         };
43 
44     }  // anonymous namespace
45 
Client(CommandSerializer * serializer,MemoryTransferService * memoryTransferService)46     Client::Client(CommandSerializer* serializer, MemoryTransferService* memoryTransferService)
47         : ClientBase(), mSerializer(serializer), mMemoryTransferService(memoryTransferService) {
48         if (mMemoryTransferService == nullptr) {
49             // If a MemoryTransferService is not provided, fall back to inline memory.
50             mOwnedMemoryTransferService = CreateInlineMemoryTransferService();
51             mMemoryTransferService = mOwnedMemoryTransferService.get();
52         }
53     }
54 
~Client()55     Client::~Client() {
56         DestroyAllObjects();
57     }
58 
DestroyAllObjects()59     void Client::DestroyAllObjects() {
60         for (auto& objectList : mObjects) {
61             ObjectType objectType = static_cast<ObjectType>(&objectList - mObjects.data());
62             if (objectType == ObjectType::Device) {
63                 continue;
64             }
65             while (!objectList.empty()) {
66                 ObjectBase* object = objectList.head()->value();
67 
68                 DestroyObjectCmd cmd;
69                 cmd.objectType = objectType;
70                 cmd.objectId = object->id;
71                 SerializeCommand(cmd);
72                 FreeObject(objectType, object);
73             }
74         }
75 
76         while (!mObjects[ObjectType::Device].empty()) {
77             ObjectBase* object = mObjects[ObjectType::Device].head()->value();
78 
79             DestroyObjectCmd cmd;
80             cmd.objectType = ObjectType::Device;
81             cmd.objectId = object->id;
82             SerializeCommand(cmd);
83             FreeObject(ObjectType::Device, object);
84         }
85     }
86 
ReserveTexture(WGPUDevice device)87     ReservedTexture Client::ReserveTexture(WGPUDevice device) {
88         auto* allocation = TextureAllocator().New(this);
89 
90         ReservedTexture result;
91         result.texture = ToAPI(allocation->object.get());
92         result.id = allocation->object->id;
93         result.generation = allocation->generation;
94         result.deviceId = FromAPI(device)->id;
95         result.deviceGeneration = DeviceAllocator().GetGeneration(FromAPI(device)->id);
96         return result;
97     }
98 
ReserveSwapChain(WGPUDevice device)99     ReservedSwapChain Client::ReserveSwapChain(WGPUDevice device) {
100         auto* allocation = SwapChainAllocator().New(this);
101 
102         ReservedSwapChain result;
103         result.swapchain = ToAPI(allocation->object.get());
104         result.id = allocation->object->id;
105         result.generation = allocation->generation;
106         result.deviceId = FromAPI(device)->id;
107         result.deviceGeneration = DeviceAllocator().GetGeneration(FromAPI(device)->id);
108         return result;
109     }
110 
ReserveDevice()111     ReservedDevice Client::ReserveDevice() {
112         auto* allocation = DeviceAllocator().New(this);
113 
114         ReservedDevice result;
115         result.device = ToAPI(allocation->object.get());
116         result.id = allocation->object->id;
117         result.generation = allocation->generation;
118         return result;
119     }
120 
ReclaimTextureReservation(const ReservedTexture & reservation)121     void Client::ReclaimTextureReservation(const ReservedTexture& reservation) {
122         TextureAllocator().Free(FromAPI(reservation.texture));
123     }
124 
ReclaimSwapChainReservation(const ReservedSwapChain & reservation)125     void Client::ReclaimSwapChainReservation(const ReservedSwapChain& reservation) {
126         SwapChainAllocator().Free(FromAPI(reservation.swapchain));
127     }
128 
ReclaimDeviceReservation(const ReservedDevice & reservation)129     void Client::ReclaimDeviceReservation(const ReservedDevice& reservation) {
130         DeviceAllocator().Free(FromAPI(reservation.device));
131     }
132 
Disconnect()133     void Client::Disconnect() {
134         mDisconnected = true;
135         mSerializer = ChunkedCommandSerializer(NoopCommandSerializer::GetInstance());
136 
137         auto& deviceList = mObjects[ObjectType::Device];
138         {
139             for (LinkNode<ObjectBase>* device = deviceList.head(); device != deviceList.end();
140                  device = device->next()) {
141                 static_cast<Device*>(device->value())
142                     ->HandleDeviceLost(WGPUDeviceLostReason_Undefined, "GPU connection lost");
143             }
144         }
145         for (auto& objectList : mObjects) {
146             for (LinkNode<ObjectBase>* object = objectList.head(); object != objectList.end();
147                  object = object->next()) {
148                 object->value()->CancelCallbacksForDisconnect();
149             }
150         }
151     }
152 
IsDisconnected() const153     bool Client::IsDisconnected() const {
154         return mDisconnected;
155     }
156 
157 }}  // namespace dawn_wire::client
158