blob: 217cf43a504f50416d57a8cc7404b88291774219 [file] [log] [blame]
Corentin Wallez4a9ef4e2018-07-18 11:40:26 +02001// Copyright 2017 The Dawn Authors
Austin Eng376f1c62017-05-30 20:03:44 -04002//
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
Corentin Wallezd37523f2018-07-24 13:53:51 +020015#include "dawn_native/Device.h"
Austin Eng376f1c62017-05-30 20:03:44 -040016
Corentin Wallezd37523f2018-07-24 13:53:51 +020017#include "dawn_native/BindGroup.h"
18#include "dawn_native/BindGroupLayout.h"
19#include "dawn_native/BlendState.h"
20#include "dawn_native/Buffer.h"
21#include "dawn_native/CommandBuffer.h"
22#include "dawn_native/ComputePipeline.h"
23#include "dawn_native/DepthStencilState.h"
24#include "dawn_native/ErrorData.h"
25#include "dawn_native/InputState.h"
26#include "dawn_native/PipelineLayout.h"
27#include "dawn_native/Queue.h"
28#include "dawn_native/RenderPassDescriptor.h"
29#include "dawn_native/RenderPipeline.h"
30#include "dawn_native/Sampler.h"
31#include "dawn_native/ShaderModule.h"
32#include "dawn_native/SwapChain.h"
33#include "dawn_native/Texture.h"
Austin Eng376f1c62017-05-30 20:03:44 -040034
35#include <unordered_set>
36
Corentin Wallez49a65d02018-07-24 16:45:45 +020037namespace dawn_native {
Austin Eng376f1c62017-05-30 20:03:44 -040038
39 // DeviceBase::Caches
40
41 // The caches are unordered_sets of pointers with special hash and compare functions
42 // to compare the value of the objects, instead of the pointers.
Corentin Wallezc1400f02017-11-24 13:59:42 -050043 using BindGroupLayoutCache = std::
44 unordered_set<BindGroupLayoutBase*, BindGroupLayoutCacheFuncs, BindGroupLayoutCacheFuncs>;
Austin Eng376f1c62017-05-30 20:03:44 -040045
46 struct DeviceBase::Caches {
47 BindGroupLayoutCache bindGroupLayouts;
48 };
49
50 // DeviceBase
51
52 DeviceBase::DeviceBase() {
Corentin Wallezfbecc282017-11-23 10:32:51 -080053 mCaches = new DeviceBase::Caches();
Austin Eng376f1c62017-05-30 20:03:44 -040054 }
55
56 DeviceBase::~DeviceBase() {
Corentin Wallezfbecc282017-11-23 10:32:51 -080057 delete mCaches;
Austin Eng376f1c62017-05-30 20:03:44 -040058 }
59
60 void DeviceBase::HandleError(const char* message) {
Corentin Wallezfbecc282017-11-23 10:32:51 -080061 if (mErrorCallback) {
62 mErrorCallback(message, mErrorUserdata);
Austin Eng376f1c62017-05-30 20:03:44 -040063 }
64 }
65
Corentin Wallez226110f2018-07-18 11:38:11 +020066 void DeviceBase::SetErrorCallback(dawn::DeviceErrorCallback callback,
67 dawn::CallbackUserdata userdata) {
Corentin Wallezfbecc282017-11-23 10:32:51 -080068 mErrorCallback = callback;
69 mErrorUserdata = userdata;
Austin Eng376f1c62017-05-30 20:03:44 -040070 }
71
72 DeviceBase* DeviceBase::GetDevice() {
73 return this;
74 }
75
Kai Ninomiya234becf2018-07-10 12:23:50 -070076 ResultOrError<BindGroupLayoutBase*> DeviceBase::GetOrCreateBindGroupLayout(
Corentin Wallez36afbb62018-07-25 17:03:23 +020077 const BindGroupLayoutDescriptor* descriptor) {
Kai Ninomiya234becf2018-07-10 12:23:50 -070078 BindGroupLayoutBase blueprint(this, descriptor, true);
79
80 auto iter = mCaches->bindGroupLayouts.find(&blueprint);
Corentin Wallezfbecc282017-11-23 10:32:51 -080081 if (iter != mCaches->bindGroupLayouts.end()) {
Corentin Wallezdf5a18d2018-04-17 16:35:23 -040082 (*iter)->Reference();
Austin Eng376f1c62017-05-30 20:03:44 -040083 return *iter;
84 }
85
Kai Ninomiya234becf2018-07-10 12:23:50 -070086 BindGroupLayoutBase* backendObj;
Corentin Wallez33ca4962018-07-18 11:45:17 +020087 DAWN_TRY_ASSIGN(backendObj, CreateBindGroupLayoutImpl(descriptor));
Corentin Wallezfbecc282017-11-23 10:32:51 -080088 mCaches->bindGroupLayouts.insert(backendObj);
Austin Eng376f1c62017-05-30 20:03:44 -040089 return backendObj;
90 }
91
92 void DeviceBase::UncacheBindGroupLayout(BindGroupLayoutBase* obj) {
Corentin Wallezfbecc282017-11-23 10:32:51 -080093 mCaches->bindGroupLayouts.erase(obj);
Austin Eng376f1c62017-05-30 20:03:44 -040094 }
95
Corentin Wallez52f23832018-07-16 17:40:08 +020096 // Object creation API methods
97
Austin Eng376f1c62017-05-30 20:03:44 -040098 BindGroupBuilder* DeviceBase::CreateBindGroupBuilder() {
99 return new BindGroupBuilder(this);
100 }
Kai Ninomiya234becf2018-07-10 12:23:50 -0700101 BindGroupLayoutBase* DeviceBase::CreateBindGroupLayout(
Corentin Wallez36afbb62018-07-25 17:03:23 +0200102 const BindGroupLayoutDescriptor* descriptor) {
Corentin Wallez52f23832018-07-16 17:40:08 +0200103 BindGroupLayoutBase* result = nullptr;
104
105 if (ConsumedError(CreateBindGroupLayoutInternal(&result, descriptor))) {
Kai Ninomiya234becf2018-07-10 12:23:50 -0700106 return nullptr;
107 }
108
Corentin Wallez52f23832018-07-16 17:40:08 +0200109 return result;
Austin Eng376f1c62017-05-30 20:03:44 -0400110 }
Austin Eng94bebe52017-07-26 16:59:53 -0400111 BlendStateBuilder* DeviceBase::CreateBlendStateBuilder() {
112 return new BlendStateBuilder(this);
113 }
Corentin Wallez82b65732018-08-22 15:37:29 +0200114 BufferBase* DeviceBase::CreateBuffer(const BufferDescriptor* descriptor) {
115 BufferBase* result = nullptr;
116
117 if (ConsumedError(CreateBufferInternal(&result, descriptor))) {
118 return nullptr;
119 }
120
121 return result;
Austin Eng376f1c62017-05-30 20:03:44 -0400122 }
123 CommandBufferBuilder* DeviceBase::CreateCommandBufferBuilder() {
124 return new CommandBufferBuilder(this);
125 }
Corentin Wallez29ced282017-07-14 10:58:07 -0400126 ComputePipelineBuilder* DeviceBase::CreateComputePipelineBuilder() {
127 return new ComputePipelineBuilder(this);
128 }
Austin Eng376f1c62017-05-30 20:03:44 -0400129 DepthStencilStateBuilder* DeviceBase::CreateDepthStencilStateBuilder() {
130 return new DepthStencilStateBuilder(this);
131 }
Austin Eng376f1c62017-05-30 20:03:44 -0400132 InputStateBuilder* DeviceBase::CreateInputStateBuilder() {
133 return new InputStateBuilder(this);
134 }
Kai Ninomiyaf53f98b2018-06-27 16:21:39 -0700135 PipelineLayoutBase* DeviceBase::CreatePipelineLayout(
Corentin Wallez36afbb62018-07-25 17:03:23 +0200136 const PipelineLayoutDescriptor* descriptor) {
Corentin Wallez52f23832018-07-16 17:40:08 +0200137 PipelineLayoutBase* result = nullptr;
138
139 if (ConsumedError(CreatePipelineLayoutInternal(&result, descriptor))) {
Kai Ninomiyaf53f98b2018-06-27 16:21:39 -0700140 return nullptr;
141 }
142
Corentin Wallez52f23832018-07-16 17:40:08 +0200143 return result;
Austin Eng376f1c62017-05-30 20:03:44 -0400144 }
Corentin Wallezb703def2018-06-14 20:26:27 -0400145 QueueBase* DeviceBase::CreateQueue() {
Corentin Wallez52f23832018-07-16 17:40:08 +0200146 QueueBase* result = nullptr;
147
148 if (ConsumedError(CreateQueueInternal(&result))) {
Corentin Wallezb703def2018-06-14 20:26:27 -0400149 return nullptr;
150 }
Corentin Wallez52f23832018-07-16 17:40:08 +0200151
152 return result;
Austin Eng376f1c62017-05-30 20:03:44 -0400153 }
Corentin Wallez8d6b5d22018-05-11 13:04:44 -0400154 RenderPassDescriptorBuilder* DeviceBase::CreateRenderPassDescriptorBuilder() {
155 return new RenderPassDescriptorBuilder(this);
Austin Eng376f1c62017-05-30 20:03:44 -0400156 }
Corentin Wallez29ced282017-07-14 10:58:07 -0400157 RenderPipelineBuilder* DeviceBase::CreateRenderPipelineBuilder() {
158 return new RenderPipelineBuilder(this);
159 }
Corentin Wallez36afbb62018-07-25 17:03:23 +0200160 SamplerBase* DeviceBase::CreateSampler(const SamplerDescriptor* descriptor) {
Corentin Wallez52f23832018-07-16 17:40:08 +0200161 SamplerBase* result = nullptr;
162
163 if (ConsumedError(CreateSamplerInternal(&result, descriptor))) {
Corentin Wallez1ae19e82018-05-17 17:09:07 -0400164 return nullptr;
165 }
Corentin Wallez50e09862018-05-28 14:26:40 -0400166
Corentin Wallez52f23832018-07-16 17:40:08 +0200167 return result;
Austin Eng376f1c62017-05-30 20:03:44 -0400168 }
Corentin Wallezdf671032018-08-20 17:01:20 +0200169 ShaderModuleBase* DeviceBase::CreateShaderModule(const ShaderModuleDescriptor* descriptor) {
170 ShaderModuleBase* result = nullptr;
171
172 if (ConsumedError(CreateShaderModuleInternal(&result, descriptor))) {
173 return nullptr;
174 }
175
176 return result;
Austin Eng376f1c62017-05-30 20:03:44 -0400177 }
Kai Ninomiyac16a67a2017-07-27 18:30:57 -0700178 SwapChainBuilder* DeviceBase::CreateSwapChainBuilder() {
179 return new SwapChainBuilder(this);
180 }
Jiawei Shao425428f2018-08-27 08:44:48 +0800181 TextureBase* DeviceBase::CreateTexture(const TextureDescriptor* descriptor) {
182 TextureBase* result = nullptr;
183
184 if (ConsumedError(CreateTextureInternal(&result, descriptor))) {
185 return nullptr;
186 }
187 return result;
Austin Eng376f1c62017-05-30 20:03:44 -0400188 }
189
Corentin Wallez52f23832018-07-16 17:40:08 +0200190 // Other Device API methods
191
Corentin Wallezdbb57292017-06-14 13:33:45 -0400192 void DeviceBase::Tick() {
193 TickImpl();
194 }
195
Austin Engf9c39d02017-07-10 11:16:51 -0400196 void DeviceBase::Reference() {
Corentin Wallezfbecc282017-11-23 10:32:51 -0800197 ASSERT(mRefCount != 0);
198 mRefCount++;
Austin Engf9c39d02017-07-10 11:16:51 -0400199 }
200
201 void DeviceBase::Release() {
Corentin Wallezfbecc282017-11-23 10:32:51 -0800202 ASSERT(mRefCount != 0);
203 mRefCount--;
204 if (mRefCount == 0) {
Austin Engf9c39d02017-07-10 11:16:51 -0400205 delete this;
206 }
207 }
208
Corentin Wallez52f23832018-07-16 17:40:08 +0200209 // Implementation details of object creation
210
211 MaybeError DeviceBase::CreateBindGroupLayoutInternal(
212 BindGroupLayoutBase** result,
Corentin Wallez36afbb62018-07-25 17:03:23 +0200213 const BindGroupLayoutDescriptor* descriptor) {
Corentin Wallez33ca4962018-07-18 11:45:17 +0200214 DAWN_TRY(ValidateBindGroupLayoutDescriptor(this, descriptor));
215 DAWN_TRY_ASSIGN(*result, GetOrCreateBindGroupLayout(descriptor));
Corentin Wallez52f23832018-07-16 17:40:08 +0200216 return {};
217 }
218
Corentin Wallez82b65732018-08-22 15:37:29 +0200219 MaybeError DeviceBase::CreateBufferInternal(BufferBase** result,
220 const BufferDescriptor* descriptor) {
221 DAWN_TRY(ValidateBufferDescriptor(this, descriptor));
222 DAWN_TRY_ASSIGN(*result, CreateBufferImpl(descriptor));
223 return {};
224 }
225
Corentin Wallez52f23832018-07-16 17:40:08 +0200226 MaybeError DeviceBase::CreatePipelineLayoutInternal(
227 PipelineLayoutBase** result,
Corentin Wallez36afbb62018-07-25 17:03:23 +0200228 const PipelineLayoutDescriptor* descriptor) {
Corentin Wallez33ca4962018-07-18 11:45:17 +0200229 DAWN_TRY(ValidatePipelineLayoutDescriptor(this, descriptor));
230 DAWN_TRY_ASSIGN(*result, CreatePipelineLayoutImpl(descriptor));
Corentin Wallez52f23832018-07-16 17:40:08 +0200231 return {};
232 }
233
234 MaybeError DeviceBase::CreateQueueInternal(QueueBase** result) {
Corentin Wallez33ca4962018-07-18 11:45:17 +0200235 DAWN_TRY_ASSIGN(*result, CreateQueueImpl());
Corentin Wallez52f23832018-07-16 17:40:08 +0200236 return {};
237 }
238
239 MaybeError DeviceBase::CreateSamplerInternal(SamplerBase** result,
Corentin Wallez36afbb62018-07-25 17:03:23 +0200240 const SamplerDescriptor* descriptor) {
Corentin Wallez33ca4962018-07-18 11:45:17 +0200241 DAWN_TRY(ValidateSamplerDescriptor(this, descriptor));
242 DAWN_TRY_ASSIGN(*result, CreateSamplerImpl(descriptor));
Corentin Wallez52f23832018-07-16 17:40:08 +0200243 return {};
244 }
245
Corentin Wallezdf671032018-08-20 17:01:20 +0200246 MaybeError DeviceBase::CreateShaderModuleInternal(ShaderModuleBase** result,
247 const ShaderModuleDescriptor* descriptor) {
248 DAWN_TRY(ValidateShaderModuleDescriptor(this, descriptor));
249 DAWN_TRY_ASSIGN(*result, CreateShaderModuleImpl(descriptor));
250 return {};
251 }
252
Jiawei Shao425428f2018-08-27 08:44:48 +0800253 MaybeError DeviceBase::CreateTextureInternal(TextureBase** result,
254 const TextureDescriptor* descriptor) {
255 DAWN_TRY(ValidateTextureDescriptor(this, descriptor));
256 DAWN_TRY_ASSIGN(*result, CreateTextureImpl(descriptor));
257 return {};
258 }
259
Corentin Wallez52f23832018-07-16 17:40:08 +0200260 // Other implementation details
261
262 void DeviceBase::ConsumeError(ErrorData* error) {
263 ASSERT(error != nullptr);
264 HandleError(error->GetMessage().c_str());
265 delete error;
266 }
267
Corentin Wallez49a65d02018-07-24 16:45:45 +0200268} // namespace dawn_native