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 #ifndef DAWNNATIVE_NULL_DEVICENULL_H_ 16 #define DAWNNATIVE_NULL_DEVICENULL_H_ 17 18 #include "dawn_native/Adapter.h" 19 #include "dawn_native/BindGroup.h" 20 #include "dawn_native/BindGroupLayout.h" 21 #include "dawn_native/Buffer.h" 22 #include "dawn_native/CommandBuffer.h" 23 #include "dawn_native/CommandEncoder.h" 24 #include "dawn_native/ComputePipeline.h" 25 #include "dawn_native/Device.h" 26 #include "dawn_native/PipelineLayout.h" 27 #include "dawn_native/QuerySet.h" 28 #include "dawn_native/Queue.h" 29 #include "dawn_native/RenderPipeline.h" 30 #include "dawn_native/RingBufferAllocator.h" 31 #include "dawn_native/Sampler.h" 32 #include "dawn_native/ShaderModule.h" 33 #include "dawn_native/StagingBuffer.h" 34 #include "dawn_native/SwapChain.h" 35 #include "dawn_native/Texture.h" 36 #include "dawn_native/ToBackend.h" 37 #include "dawn_native/dawn_platform.h" 38 39 namespace dawn_native { namespace null { 40 41 class Adapter; 42 class BindGroup; 43 class BindGroupLayout; 44 class Buffer; 45 class CommandBuffer; 46 class ComputePipeline; 47 class Device; 48 using PipelineLayout = PipelineLayoutBase; 49 class QuerySet; 50 class Queue; 51 class RenderPipeline; 52 using Sampler = SamplerBase; 53 class ShaderModule; 54 class SwapChain; 55 using Texture = TextureBase; 56 using TextureView = TextureViewBase; 57 58 struct NullBackendTraits { 59 using AdapterType = Adapter; 60 using BindGroupType = BindGroup; 61 using BindGroupLayoutType = BindGroupLayout; 62 using BufferType = Buffer; 63 using CommandBufferType = CommandBuffer; 64 using ComputePipelineType = ComputePipeline; 65 using DeviceType = Device; 66 using PipelineLayoutType = PipelineLayout; 67 using QuerySetType = QuerySet; 68 using QueueType = Queue; 69 using RenderPipelineType = RenderPipeline; 70 using SamplerType = Sampler; 71 using ShaderModuleType = ShaderModule; 72 using SwapChainType = SwapChain; 73 using TextureType = Texture; 74 using TextureViewType = TextureView; 75 }; 76 77 template <typename T> 78 auto ToBackend(T&& common) -> decltype(ToBackendBase<NullBackendTraits>(common)) { 79 return ToBackendBase<NullBackendTraits>(common); 80 } 81 82 struct PendingOperation { 83 virtual ~PendingOperation() = default; 84 virtual void Execute() = 0; 85 }; 86 87 class Device final : public DeviceBase { 88 public: 89 static ResultOrError<Device*> Create(Adapter* adapter, 90 const DawnDeviceDescriptor* descriptor); 91 ~Device() override; 92 93 MaybeError Initialize(); 94 95 ResultOrError<Ref<CommandBufferBase>> CreateCommandBuffer( 96 CommandEncoder* encoder, 97 const CommandBufferDescriptor* descriptor) override; 98 99 MaybeError TickImpl() override; 100 101 void AddPendingOperation(std::unique_ptr<PendingOperation> operation); 102 MaybeError SubmitPendingOperations(); 103 104 ResultOrError<std::unique_ptr<StagingBufferBase>> CreateStagingBuffer(size_t size) override; 105 MaybeError CopyFromStagingToBuffer(StagingBufferBase* source, 106 uint64_t sourceOffset, 107 BufferBase* destination, 108 uint64_t destinationOffset, 109 uint64_t size) override; 110 MaybeError CopyFromStagingToTexture(const StagingBufferBase* source, 111 const TextureDataLayout& src, 112 TextureCopy* dst, 113 const Extent3D& copySizePixels) override; 114 115 MaybeError IncrementMemoryUsage(uint64_t bytes); 116 void DecrementMemoryUsage(uint64_t bytes); 117 118 uint32_t GetOptimalBytesPerRowAlignment() const override; 119 uint64_t GetOptimalBufferToTextureCopyOffsetAlignment() const override; 120 121 float GetTimestampPeriodInNS() const override; 122 123 private: 124 using DeviceBase::DeviceBase; 125 126 ResultOrError<Ref<BindGroupBase>> CreateBindGroupImpl( 127 const BindGroupDescriptor* descriptor) override; 128 ResultOrError<Ref<BindGroupLayoutBase>> CreateBindGroupLayoutImpl( 129 const BindGroupLayoutDescriptor* descriptor, 130 PipelineCompatibilityToken pipelineCompatibilityToken) override; 131 ResultOrError<Ref<BufferBase>> CreateBufferImpl( 132 const BufferDescriptor* descriptor) override; 133 Ref<ComputePipelineBase> CreateUninitializedComputePipelineImpl( 134 const ComputePipelineDescriptor* descriptor) override; 135 ResultOrError<Ref<PipelineLayoutBase>> CreatePipelineLayoutImpl( 136 const PipelineLayoutDescriptor* descriptor) override; 137 ResultOrError<Ref<QuerySetBase>> CreateQuerySetImpl( 138 const QuerySetDescriptor* descriptor) override; 139 Ref<RenderPipelineBase> CreateUninitializedRenderPipelineImpl( 140 const RenderPipelineDescriptor* descriptor) override; 141 ResultOrError<Ref<SamplerBase>> CreateSamplerImpl( 142 const SamplerDescriptor* descriptor) override; 143 ResultOrError<Ref<ShaderModuleBase>> CreateShaderModuleImpl( 144 const ShaderModuleDescriptor* descriptor, 145 ShaderModuleParseResult* parseResult) override; 146 ResultOrError<Ref<SwapChainBase>> CreateSwapChainImpl( 147 const SwapChainDescriptor* descriptor) override; 148 ResultOrError<Ref<NewSwapChainBase>> CreateSwapChainImpl( 149 Surface* surface, 150 NewSwapChainBase* previousSwapChain, 151 const SwapChainDescriptor* descriptor) override; 152 ResultOrError<Ref<TextureBase>> CreateTextureImpl( 153 const TextureDescriptor* descriptor) override; 154 ResultOrError<Ref<TextureViewBase>> CreateTextureViewImpl( 155 TextureBase* texture, 156 const TextureViewDescriptor* descriptor) override; 157 158 ResultOrError<ExecutionSerial> CheckAndUpdateCompletedSerials() override; 159 160 void DestroyImpl() override; 161 MaybeError WaitForIdleForDestruction() override; 162 163 std::vector<std::unique_ptr<PendingOperation>> mPendingOperations; 164 165 static constexpr uint64_t kMaxMemoryUsage = 512 * 1024 * 1024; 166 size_t mMemoryUsage = 0; 167 }; 168 169 class Adapter : public AdapterBase { 170 public: 171 Adapter(InstanceBase* instance); 172 ~Adapter() override; 173 174 // AdapterBase Implementation 175 bool SupportsExternalImages() const override; 176 177 // Used for the tests that intend to use an adapter without all features enabled. 178 void SetSupportedFeatures(const std::vector<const char*>& requiredFeatures); 179 180 private: 181 MaybeError InitializeImpl() override; 182 MaybeError InitializeSupportedFeaturesImpl() override; 183 MaybeError InitializeSupportedLimitsImpl(CombinedLimits* limits) override; 184 185 ResultOrError<DeviceBase*> CreateDeviceImpl( 186 const DawnDeviceDescriptor* descriptor) override; 187 }; 188 189 // Helper class so |BindGroup| can allocate memory for its binding data, 190 // before calling the BindGroupBase base class constructor. 191 class BindGroupDataHolder { 192 protected: 193 explicit BindGroupDataHolder(size_t size); 194 ~BindGroupDataHolder(); 195 196 void* mBindingDataAllocation; 197 }; 198 199 // We don't have the complexity of placement-allocation of bind group data in 200 // the Null backend. This class, keeps the binding data in a separate allocation for simplicity. 201 class BindGroup final : private BindGroupDataHolder, public BindGroupBase { 202 public: 203 BindGroup(DeviceBase* device, const BindGroupDescriptor* descriptor); 204 205 private: 206 ~BindGroup() override = default; 207 }; 208 209 class BindGroupLayout final : public BindGroupLayoutBase { 210 public: 211 BindGroupLayout(DeviceBase* device, 212 const BindGroupLayoutDescriptor* descriptor, 213 PipelineCompatibilityToken pipelineCompatibilityToken); 214 215 private: 216 ~BindGroupLayout() override = default; 217 }; 218 219 class Buffer final : public BufferBase { 220 public: 221 Buffer(Device* device, const BufferDescriptor* descriptor); 222 223 void CopyFromStaging(StagingBufferBase* staging, 224 uint64_t sourceOffset, 225 uint64_t destinationOffset, 226 uint64_t size); 227 228 void DoWriteBuffer(uint64_t bufferOffset, const void* data, size_t size); 229 230 private: 231 MaybeError MapAsyncImpl(wgpu::MapMode mode, size_t offset, size_t size) override; 232 void UnmapImpl() override; 233 void DestroyImpl() override; 234 bool IsCPUWritableAtCreation() const override; 235 MaybeError MapAtCreationImpl() override; 236 void* GetMappedPointerImpl() override; 237 238 std::unique_ptr<uint8_t[]> mBackingData; 239 }; 240 241 class CommandBuffer final : public CommandBufferBase { 242 public: 243 CommandBuffer(CommandEncoder* encoder, const CommandBufferDescriptor* descriptor); 244 }; 245 246 class QuerySet final : public QuerySetBase { 247 public: 248 QuerySet(Device* device, const QuerySetDescriptor* descriptor); 249 }; 250 251 class Queue final : public QueueBase { 252 public: 253 Queue(Device* device); 254 255 private: 256 ~Queue() override; 257 MaybeError SubmitImpl(uint32_t commandCount, CommandBufferBase* const* commands) override; 258 MaybeError WriteBufferImpl(BufferBase* buffer, 259 uint64_t bufferOffset, 260 const void* data, 261 size_t size) override; 262 }; 263 264 class ComputePipeline final : public ComputePipelineBase { 265 public: 266 using ComputePipelineBase::ComputePipelineBase; 267 268 MaybeError Initialize() override; 269 }; 270 271 class RenderPipeline final : public RenderPipelineBase { 272 public: 273 using RenderPipelineBase::RenderPipelineBase; 274 275 MaybeError Initialize() override; 276 }; 277 278 class ShaderModule final : public ShaderModuleBase { 279 public: 280 using ShaderModuleBase::ShaderModuleBase; 281 282 MaybeError Initialize(ShaderModuleParseResult* parseResult); 283 }; 284 285 class SwapChain final : public NewSwapChainBase { 286 public: 287 static ResultOrError<Ref<SwapChain>> Create(Device* device, 288 Surface* surface, 289 NewSwapChainBase* previousSwapChain, 290 const SwapChainDescriptor* descriptor); 291 ~SwapChain() override; 292 293 private: 294 using NewSwapChainBase::NewSwapChainBase; 295 MaybeError Initialize(NewSwapChainBase* previousSwapChain); 296 297 Ref<Texture> mTexture; 298 299 MaybeError PresentImpl() override; 300 ResultOrError<TextureViewBase*> GetCurrentTextureViewImpl() override; 301 void DetachFromSurfaceImpl() override; 302 }; 303 304 class OldSwapChain final : public OldSwapChainBase { 305 public: 306 OldSwapChain(Device* device, const SwapChainDescriptor* descriptor); 307 308 protected: 309 ~OldSwapChain() override; 310 TextureBase* GetNextTextureImpl(const TextureDescriptor* descriptor) override; 311 MaybeError OnBeforePresent(TextureViewBase*) override; 312 }; 313 314 class NativeSwapChainImpl { 315 public: 316 using WSIContext = struct {}; 317 void Init(WSIContext* context); 318 DawnSwapChainError Configure(WGPUTextureFormat format, 319 WGPUTextureUsage, 320 uint32_t width, 321 uint32_t height); 322 DawnSwapChainError GetNextTexture(DawnSwapChainNextTexture* nextTexture); 323 DawnSwapChainError Present(); 324 wgpu::TextureFormat GetPreferredFormat() const; 325 }; 326 327 class StagingBuffer : public StagingBufferBase { 328 public: 329 StagingBuffer(size_t size, Device* device); 330 ~StagingBuffer() override; 331 MaybeError Initialize() override; 332 333 private: 334 Device* mDevice; 335 std::unique_ptr<uint8_t[]> mBuffer; 336 }; 337 338 }} // namespace dawn_native::null 339 340 #endif // DAWNNATIVE_NULL_DEVICENULL_H_ 341