// Copyright 2017 The Dawn Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef DAWNNATIVE_NULL_DEVICENULL_H_ #define DAWNNATIVE_NULL_DEVICENULL_H_ #include "dawn_native/Adapter.h" #include "dawn_native/BindGroup.h" #include "dawn_native/BindGroupLayout.h" #include "dawn_native/Buffer.h" #include "dawn_native/CommandBuffer.h" #include "dawn_native/CommandEncoder.h" #include "dawn_native/ComputePipeline.h" #include "dawn_native/Device.h" #include "dawn_native/PipelineLayout.h" #include "dawn_native/QuerySet.h" #include "dawn_native/Queue.h" #include "dawn_native/RenderPipeline.h" #include "dawn_native/RingBufferAllocator.h" #include "dawn_native/Sampler.h" #include "dawn_native/ShaderModule.h" #include "dawn_native/StagingBuffer.h" #include "dawn_native/SwapChain.h" #include "dawn_native/Texture.h" #include "dawn_native/ToBackend.h" #include "dawn_native/dawn_platform.h" namespace dawn_native { namespace null { class Adapter; class BindGroup; using BindGroupLayout = BindGroupLayoutBase; class Buffer; class CommandBuffer; using ComputePipeline = ComputePipelineBase; class Device; using PipelineLayout = PipelineLayoutBase; class QuerySet; class Queue; using RenderPipeline = RenderPipelineBase; using Sampler = SamplerBase; class ShaderModule; class SwapChain; using Texture = TextureBase; using TextureView = TextureViewBase; struct NullBackendTraits { using AdapterType = Adapter; using BindGroupType = BindGroup; using BindGroupLayoutType = BindGroupLayout; using BufferType = Buffer; using CommandBufferType = CommandBuffer; using ComputePipelineType = ComputePipeline; using DeviceType = Device; using PipelineLayoutType = PipelineLayout; using QuerySetType = QuerySet; using QueueType = Queue; using RenderPipelineType = RenderPipeline; using SamplerType = Sampler; using ShaderModuleType = ShaderModule; using SwapChainType = SwapChain; using TextureType = Texture; using TextureViewType = TextureView; }; template auto ToBackend(T&& common) -> decltype(ToBackendBase(common)) { return ToBackendBase(common); } struct PendingOperation { virtual ~PendingOperation() = default; virtual void Execute() = 0; }; class Device : public DeviceBase { public: static ResultOrError Create(Adapter* adapter, const DeviceDescriptor* descriptor); ~Device() override; MaybeError Initialize(); ResultOrError> CreateCommandBuffer( CommandEncoder* encoder, const CommandBufferDescriptor* descriptor) override; MaybeError TickImpl() override; void AddPendingOperation(std::unique_ptr operation); void SubmitPendingOperations(); ResultOrError> CreateStagingBuffer(size_t size) override; MaybeError CopyFromStagingToBuffer(StagingBufferBase* source, uint64_t sourceOffset, BufferBase* destination, uint64_t destinationOffset, uint64_t size) override; MaybeError CopyFromStagingToTexture(const StagingBufferBase* source, const TextureDataLayout& src, TextureCopy* dst, const Extent3D& copySizePixels) override; MaybeError IncrementMemoryUsage(uint64_t bytes); void DecrementMemoryUsage(uint64_t bytes); uint32_t GetOptimalBytesPerRowAlignment() const override; uint64_t GetOptimalBufferToTextureCopyOffsetAlignment() const override; float GetTimestampPeriodInNS() const override; private: using DeviceBase::DeviceBase; ResultOrError> CreateBindGroupImpl( const BindGroupDescriptor* descriptor) override; ResultOrError> CreateBindGroupLayoutImpl( const BindGroupLayoutDescriptor* descriptor) override; ResultOrError> CreateBufferImpl( const BufferDescriptor* descriptor) override; ResultOrError> CreateComputePipelineImpl( const ComputePipelineDescriptor* descriptor) override; ResultOrError> CreatePipelineLayoutImpl( const PipelineLayoutDescriptor* descriptor) override; ResultOrError> CreateQuerySetImpl( const QuerySetDescriptor* descriptor) override; ResultOrError> CreateRenderPipelineImpl( const RenderPipelineDescriptor* descriptor) override; ResultOrError> CreateSamplerImpl( const SamplerDescriptor* descriptor) override; ResultOrError> CreateShaderModuleImpl( const ShaderModuleDescriptor* descriptor, ShaderModuleParseResult* parseResult) override; ResultOrError> CreateSwapChainImpl( const SwapChainDescriptor* descriptor) override; ResultOrError> CreateSwapChainImpl( Surface* surface, NewSwapChainBase* previousSwapChain, const SwapChainDescriptor* descriptor) override; ResultOrError> CreateTextureImpl( const TextureDescriptor* descriptor) override; ResultOrError> CreateTextureViewImpl( TextureBase* texture, const TextureViewDescriptor* descriptor) override; ExecutionSerial CheckAndUpdateCompletedSerials() override; void ShutDownImpl() override; MaybeError WaitForIdleForDestruction() override; std::vector> mPendingOperations; static constexpr uint64_t kMaxMemoryUsage = 256 * 1024 * 1024; size_t mMemoryUsage = 0; }; class Adapter : public AdapterBase { public: Adapter(InstanceBase* instance); ~Adapter() override; // Used for the tests that intend to use an adapter without all extensions enabled. void SetSupportedExtensions(const std::vector& requiredExtensions); private: ResultOrError CreateDeviceImpl(const DeviceDescriptor* descriptor) override; }; // Helper class so |BindGroup| can allocate memory for its binding data, // before calling the BindGroupBase base class constructor. class BindGroupDataHolder { protected: explicit BindGroupDataHolder(size_t size); ~BindGroupDataHolder(); void* mBindingDataAllocation; }; // We don't have the complexity of placement-allocation of bind group data in // the Null backend. This class, keeps the binding data in a separate allocation for simplicity. class BindGroup final : private BindGroupDataHolder, public BindGroupBase { public: BindGroup(DeviceBase* device, const BindGroupDescriptor* descriptor); private: ~BindGroup() override = default; }; class Buffer final : public BufferBase { public: Buffer(Device* device, const BufferDescriptor* descriptor); void CopyFromStaging(StagingBufferBase* staging, uint64_t sourceOffset, uint64_t destinationOffset, uint64_t size); void DoWriteBuffer(uint64_t bufferOffset, const void* data, size_t size); private: ~Buffer() override; MaybeError MapAsyncImpl(wgpu::MapMode mode, size_t offset, size_t size) override; void UnmapImpl() override; void DestroyImpl() override; bool IsCPUWritableAtCreation() const override; MaybeError MapAtCreationImpl() override; void* GetMappedPointerImpl() override; std::unique_ptr mBackingData; }; class CommandBuffer final : public CommandBufferBase { public: CommandBuffer(CommandEncoder* encoder, const CommandBufferDescriptor* descriptor); }; class QuerySet final : public QuerySetBase { public: QuerySet(Device* device, const QuerySetDescriptor* descriptor); private: ~QuerySet() override; void DestroyImpl() override; }; class Queue final : public QueueBase { public: Queue(Device* device); private: ~Queue() override; MaybeError SubmitImpl(uint32_t commandCount, CommandBufferBase* const* commands) override; MaybeError WriteBufferImpl(BufferBase* buffer, uint64_t bufferOffset, const void* data, size_t size) override; }; class ShaderModule final : public ShaderModuleBase { public: using ShaderModuleBase::ShaderModuleBase; MaybeError Initialize(ShaderModuleParseResult* parseResult); }; class SwapChain final : public NewSwapChainBase { public: static ResultOrError> Create(Device* device, Surface* surface, NewSwapChainBase* previousSwapChain, const SwapChainDescriptor* descriptor); ~SwapChain() override; private: using NewSwapChainBase::NewSwapChainBase; MaybeError Initialize(NewSwapChainBase* previousSwapChain); Ref mTexture; MaybeError PresentImpl() override; ResultOrError GetCurrentTextureViewImpl() override; void DetachFromSurfaceImpl() override; }; class OldSwapChain final : public OldSwapChainBase { public: OldSwapChain(Device* device, const SwapChainDescriptor* descriptor); protected: ~OldSwapChain() override; TextureBase* GetNextTextureImpl(const TextureDescriptor* descriptor) override; MaybeError OnBeforePresent(TextureViewBase*) override; }; class NativeSwapChainImpl { public: using WSIContext = struct {}; void Init(WSIContext* context); DawnSwapChainError Configure(WGPUTextureFormat format, WGPUTextureUsage, uint32_t width, uint32_t height); DawnSwapChainError GetNextTexture(DawnSwapChainNextTexture* nextTexture); DawnSwapChainError Present(); wgpu::TextureFormat GetPreferredFormat() const; }; class StagingBuffer : public StagingBufferBase { public: StagingBuffer(size_t size, Device* device); ~StagingBuffer() override; MaybeError Initialize() override; private: Device* mDevice; std::unique_ptr mBuffer; }; }} // namespace dawn_native::null #endif // DAWNNATIVE_NULL_DEVICENULL_H_