Austin Eng 4d15609d26 Add a toggle to disable Dawn validation
Trusted users of Dawn should be able to use it without the
overhead of command validation. This patch adds the toggle and
skips validation for object creation.

Bug: dawn:271
Change-Id: Ica9a1988177685d73e2c36e05c4d525ad1ab0fdb
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/13802
Commit-Queue: Austin Eng <enga@chromium.org>
Reviewed-by: Jiawei Shao <jiawei.shao@intel.com>
2019-11-21 00:48:39 +00:00

288 lines
13 KiB
C++

// 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_DEVICE_H_
#define DAWNNATIVE_DEVICE_H_
#include "common/Serial.h"
#include "dawn_native/Error.h"
#include "dawn_native/Extensions.h"
#include "dawn_native/Format.h"
#include "dawn_native/Forward.h"
#include "dawn_native/ObjectBase.h"
#include "dawn_native/Toggles.h"
#include "dawn_native/DawnNative.h"
#include "dawn_native/dawn_platform.h"
#include <memory>
namespace dawn_native {
using ErrorCallback = void (*)(const char* errorMessage, void* userData);
class AdapterBase;
class AttachmentState;
class AttachmentStateBlueprint;
class ErrorScope;
class ErrorScopeTracker;
class FenceSignalTracker;
class DynamicUploader;
class StagingBufferBase;
class DeviceBase {
public:
DeviceBase(AdapterBase* adapter, const DeviceDescriptor* descriptor);
virtual ~DeviceBase();
void HandleError(wgpu::ErrorType type, const char* message);
bool ConsumedError(MaybeError maybeError) {
if (DAWN_UNLIKELY(maybeError.IsError())) {
ConsumeError(maybeError.AcquireError());
return true;
}
return false;
}
template <typename T>
bool ConsumedError(ResultOrError<T> resultOrError, T* result) {
if (DAWN_UNLIKELY(resultOrError.IsError())) {
ConsumeError(resultOrError.AcquireError());
return true;
}
*result = resultOrError.AcquireSuccess();
return false;
}
MaybeError ValidateObject(const ObjectBase* object) const;
AdapterBase* GetAdapter() const;
dawn_platform::Platform* GetPlatform() const;
ErrorScopeTracker* GetErrorScopeTracker() const;
FenceSignalTracker* GetFenceSignalTracker() const;
// Returns the Format corresponding to the wgpu::TextureFormat or an error if the format
// isn't a valid wgpu::TextureFormat or isn't supported by this device.
// The pointer returned has the same lifetime as the device.
ResultOrError<const Format*> GetInternalFormat(wgpu::TextureFormat format) const;
// Returns the Format corresponding to the wgpu::TextureFormat and assumes the format is
// valid and supported.
// The reference returned has the same lifetime as the device.
const Format& GetValidInternalFormat(wgpu::TextureFormat format) const;
virtual CommandBufferBase* CreateCommandBuffer(
CommandEncoder* encoder,
const CommandBufferDescriptor* descriptor) = 0;
virtual Serial GetCompletedCommandSerial() const = 0;
virtual Serial GetLastSubmittedCommandSerial() const = 0;
virtual Serial GetPendingCommandSerial() const = 0;
virtual MaybeError TickImpl() = 0;
// Many Dawn objects are completely immutable once created which means that if two
// creations are given the same arguments, they can return the same object. Reusing
// objects will help make comparisons between objects by a single pointer comparison.
//
// Technically no object is immutable as they have a reference count, and an
// application with reference-counting issues could "see" that objects are reused.
// This is solved by automatic-reference counting, and also the fact that when using
// the client-server wire every creation will get a different proxy object, with a
// different reference count.
//
// When trying to create an object, we give both the descriptor and an example of what
// the created object will be, the "blueprint". The blueprint is just a FooBase object
// instead of a backend Foo object. If the blueprint doesn't match an object in the
// cache, then the descriptor is used to make a new object.
ResultOrError<BindGroupLayoutBase*> GetOrCreateBindGroupLayout(
const BindGroupLayoutDescriptor* descriptor);
void UncacheBindGroupLayout(BindGroupLayoutBase* obj);
ResultOrError<ComputePipelineBase*> GetOrCreateComputePipeline(
const ComputePipelineDescriptor* descriptor);
void UncacheComputePipeline(ComputePipelineBase* obj);
ResultOrError<PipelineLayoutBase*> GetOrCreatePipelineLayout(
const PipelineLayoutDescriptor* descriptor);
void UncachePipelineLayout(PipelineLayoutBase* obj);
ResultOrError<RenderPipelineBase*> GetOrCreateRenderPipeline(
const RenderPipelineDescriptor* descriptor);
void UncacheRenderPipeline(RenderPipelineBase* obj);
ResultOrError<SamplerBase*> GetOrCreateSampler(const SamplerDescriptor* descriptor);
void UncacheSampler(SamplerBase* obj);
ResultOrError<ShaderModuleBase*> GetOrCreateShaderModule(
const ShaderModuleDescriptor* descriptor);
void UncacheShaderModule(ShaderModuleBase* obj);
Ref<AttachmentState> GetOrCreateAttachmentState(AttachmentStateBlueprint* blueprint);
Ref<AttachmentState> GetOrCreateAttachmentState(
const RenderBundleEncoderDescriptor* descriptor);
Ref<AttachmentState> GetOrCreateAttachmentState(const RenderPipelineDescriptor* descriptor);
Ref<AttachmentState> GetOrCreateAttachmentState(const RenderPassDescriptor* descriptor);
void UncacheAttachmentState(AttachmentState* obj);
// Dawn API
BindGroupBase* CreateBindGroup(const BindGroupDescriptor* descriptor);
BindGroupLayoutBase* CreateBindGroupLayout(const BindGroupLayoutDescriptor* descriptor);
BufferBase* CreateBuffer(const BufferDescriptor* descriptor);
WGPUCreateBufferMappedResult CreateBufferMapped(const BufferDescriptor* descriptor);
void CreateBufferMappedAsync(const BufferDescriptor* descriptor,
wgpu::BufferCreateMappedCallback callback,
void* userdata);
CommandEncoder* CreateCommandEncoder(const CommandEncoderDescriptor* descriptor);
ComputePipelineBase* CreateComputePipeline(const ComputePipelineDescriptor* descriptor);
PipelineLayoutBase* CreatePipelineLayout(const PipelineLayoutDescriptor* descriptor);
QueueBase* CreateQueue();
RenderBundleEncoder* CreateRenderBundleEncoder(
const RenderBundleEncoderDescriptor* descriptor);
RenderPipelineBase* CreateRenderPipeline(const RenderPipelineDescriptor* descriptor);
SamplerBase* CreateSampler(const SamplerDescriptor* descriptor);
ShaderModuleBase* CreateShaderModule(const ShaderModuleDescriptor* descriptor);
SwapChainBase* CreateSwapChain(const SwapChainDescriptor* descriptor);
TextureBase* CreateTexture(const TextureDescriptor* descriptor);
TextureViewBase* CreateTextureView(TextureBase* texture,
const TextureViewDescriptor* descriptor);
void InjectError(wgpu::ErrorType type, const char* message);
void Tick();
void SetUncapturedErrorCallback(wgpu::ErrorCallback callback, void* userdata);
void PushErrorScope(wgpu::ErrorFilter filter);
bool PopErrorScope(wgpu::ErrorCallback callback, void* userdata);
ErrorScope* GetCurrentErrorScope();
void Reference();
void Release();
virtual ResultOrError<std::unique_ptr<StagingBufferBase>> CreateStagingBuffer(
size_t size) = 0;
virtual MaybeError CopyFromStagingToBuffer(StagingBufferBase* source,
uint64_t sourceOffset,
BufferBase* destination,
uint64_t destinationOffset,
uint64_t size) = 0;
DynamicUploader* GetDynamicUploader() const;
std::vector<const char*> GetEnabledExtensions() const;
std::vector<const char*> GetTogglesUsed() const;
bool IsExtensionEnabled(Extension extension) const;
bool IsToggleEnabled(Toggle toggle) const;
bool IsValidationEnabled() const;
size_t GetLazyClearCountForTesting();
void IncrementLazyClearCountForTesting();
protected:
void SetToggle(Toggle toggle, bool isEnabled);
void ApplyToggleOverrides(const DeviceDescriptor* deviceDescriptor);
std::unique_ptr<DynamicUploader> mDynamicUploader;
private:
virtual ResultOrError<BindGroupBase*> CreateBindGroupImpl(
const BindGroupDescriptor* descriptor) = 0;
virtual ResultOrError<BindGroupLayoutBase*> CreateBindGroupLayoutImpl(
const BindGroupLayoutDescriptor* descriptor) = 0;
virtual ResultOrError<BufferBase*> CreateBufferImpl(const BufferDescriptor* descriptor) = 0;
virtual ResultOrError<ComputePipelineBase*> CreateComputePipelineImpl(
const ComputePipelineDescriptor* descriptor) = 0;
virtual ResultOrError<PipelineLayoutBase*> CreatePipelineLayoutImpl(
const PipelineLayoutDescriptor* descriptor) = 0;
virtual ResultOrError<QueueBase*> CreateQueueImpl() = 0;
virtual ResultOrError<RenderPipelineBase*> CreateRenderPipelineImpl(
const RenderPipelineDescriptor* descriptor) = 0;
virtual ResultOrError<SamplerBase*> CreateSamplerImpl(
const SamplerDescriptor* descriptor) = 0;
virtual ResultOrError<ShaderModuleBase*> CreateShaderModuleImpl(
const ShaderModuleDescriptor* descriptor) = 0;
virtual ResultOrError<SwapChainBase*> CreateSwapChainImpl(
const SwapChainDescriptor* descriptor) = 0;
virtual ResultOrError<TextureBase*> CreateTextureImpl(
const TextureDescriptor* descriptor) = 0;
virtual ResultOrError<TextureViewBase*> CreateTextureViewImpl(
TextureBase* texture,
const TextureViewDescriptor* descriptor) = 0;
MaybeError CreateBindGroupInternal(BindGroupBase** result,
const BindGroupDescriptor* descriptor);
MaybeError CreateBindGroupLayoutInternal(BindGroupLayoutBase** result,
const BindGroupLayoutDescriptor* descriptor);
MaybeError CreateBufferInternal(BufferBase** result, const BufferDescriptor* descriptor);
MaybeError CreateComputePipelineInternal(ComputePipelineBase** result,
const ComputePipelineDescriptor* descriptor);
MaybeError CreatePipelineLayoutInternal(PipelineLayoutBase** result,
const PipelineLayoutDescriptor* descriptor);
MaybeError CreateQueueInternal(QueueBase** result);
MaybeError CreateRenderBundleEncoderInternal(
RenderBundleEncoder** result,
const RenderBundleEncoderDescriptor* descriptor);
MaybeError CreateRenderPipelineInternal(RenderPipelineBase** result,
const RenderPipelineDescriptor* descriptor);
MaybeError CreateSamplerInternal(SamplerBase** result, const SamplerDescriptor* descriptor);
MaybeError CreateShaderModuleInternal(ShaderModuleBase** result,
const ShaderModuleDescriptor* descriptor);
MaybeError CreateSwapChainInternal(SwapChainBase** result,
const SwapChainDescriptor* descriptor);
MaybeError CreateTextureInternal(TextureBase** result, const TextureDescriptor* descriptor);
MaybeError CreateTextureViewInternal(TextureViewBase** result,
TextureBase* texture,
const TextureViewDescriptor* descriptor);
void ApplyExtensions(const DeviceDescriptor* deviceDescriptor);
void SetDefaultToggles();
void ConsumeError(ErrorData* error);
AdapterBase* mAdapter = nullptr;
Ref<ErrorScope> mRootErrorScope;
Ref<ErrorScope> mCurrentErrorScope;
// The object caches aren't exposed in the header as they would require a lot of
// additional includes.
struct Caches;
std::unique_ptr<Caches> mCaches;
struct DeferredCreateBufferMappedAsync {
wgpu::BufferCreateMappedCallback callback;
WGPUBufferMapAsyncStatus status;
WGPUCreateBufferMappedResult result;
void* userdata;
};
std::unique_ptr<ErrorScopeTracker> mErrorScopeTracker;
std::unique_ptr<FenceSignalTracker> mFenceSignalTracker;
std::vector<DeferredCreateBufferMappedAsync> mDeferredCreateBufferMappedAsyncResults;
uint32_t mRefCount = 1;
FormatTable mFormatTable;
TogglesSet mTogglesSet;
size_t mLazyClearCountForTesting = 0;
ExtensionsSet mEnabledExtensions;
};
} // namespace dawn_native
#endif // DAWNNATIVE_DEVICE_H_