blob: 500ea2e8f92ff507c664bc47c1834636420fdabb [file] [log] [blame]
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_DEVICE_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_DEVICE_H_
#include <bitset>
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_property.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_texture_format.h"
#include "third_party/blink/renderer/core/dom/events/event_target.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/webgpu/dawn_object.h"
#include "third_party/blink/renderer/platform/graphics/gpu/webgpu_callback.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
namespace blink {
class ExecutionContext;
class ExternalTextureCache;
class GPUAdapter;
class GPUBuffer;
class GPUBufferDescriptor;
class GPUCommandEncoder;
class GPUCommandEncoderDescriptor;
class GPUBindGroup;
class GPUBindGroupDescriptor;
class GPUBindGroupLayout;
class GPUBindGroupLayoutDescriptor;
class GPUComputePipeline;
class GPUComputePipelineDescriptor;
class GPUDeviceDescriptor;
class GPUDeviceLostInfo;
class GPUExternalTexture;
class GPUExternalTextureDescriptor;
class GPUPipelineLayout;
class GPUPipelineLayoutDescriptor;
class GPUQuerySet;
class GPUQuerySetDescriptor;
class GPUQueue;
class GPURenderBundleEncoder;
class GPURenderBundleEncoderDescriptor;
class GPURenderPipeline;
class GPURenderPipelineDescriptor;
class GPUSampler;
class GPUSamplerDescriptor;
class GPUShaderModule;
class GPUShaderModuleDescriptor;
class GPUSupportedFeatures;
class GPUSupportedLimits;
class GPUTexture;
class GPUTextureDescriptor;
class ScriptPromiseResolver;
class ScriptState;
class V8GPUErrorFilter;
// Singleton warnings are messages that can only be raised once per device. They
// should be used for warnings of behavior that is not invalid but may have
// performance issues or side effects that the developer may overlook since a
// regular warning is not raised.
enum class GPUSingletonWarning {
kNonPreferredFormat,
kDepthKey,
kTimestampArray,
kCount, // Must be last
};
class GPUDevice final : public EventTargetWithInlineData,
public ExecutionContextClient,
public DawnObject<WGPUDevice> {
DEFINE_WRAPPERTYPEINFO();
USING_PRE_FINALIZER(GPUDevice, Dispose);
public:
explicit GPUDevice(ExecutionContext* execution_context,
scoped_refptr<DawnControlClientHolder> dawn_control_client,
GPUAdapter* adapter,
WGPUDevice dawn_device,
const GPUDeviceDescriptor* descriptor,
GPUDeviceLostInfo* lost_info = nullptr);
GPUDevice(const GPUDevice&) = delete;
GPUDevice& operator=(const GPUDevice&) = delete;
~GPUDevice() override;
void Trace(Visitor* visitor) const override;
// gpu_device.idl
GPUAdapter* adapter() const;
GPUSupportedFeatures* features() const;
GPUSupportedLimits* limits() const { return limits_; }
ScriptPromise lost(ScriptState* script_state);
GPUQueue* queue();
bool destroyed() const;
void destroy(v8::Isolate* isolate);
GPUBuffer* createBuffer(const GPUBufferDescriptor* descriptor,
ExceptionState& exception_state);
GPUTexture* createTexture(const GPUTextureDescriptor* descriptor,
ExceptionState& exception_state);
GPUSampler* createSampler(const GPUSamplerDescriptor* descriptor);
GPUExternalTexture* importExternalTexture(
ScriptState* script_state,
const GPUExternalTextureDescriptor* descriptor,
ExceptionState& exception_state);
GPUBindGroup* createBindGroup(const GPUBindGroupDescriptor* descriptor,
ExceptionState& exception_state);
GPUBindGroupLayout* createBindGroupLayout(
const GPUBindGroupLayoutDescriptor* descriptor,
ExceptionState& exception_state);
GPUPipelineLayout* createPipelineLayout(
const GPUPipelineLayoutDescriptor* descriptor);
GPUShaderModule* createShaderModule(
const GPUShaderModuleDescriptor* descriptor,
ExceptionState& exception_state);
GPURenderPipeline* createRenderPipeline(
ScriptState* script_state,
const GPURenderPipelineDescriptor* descriptor);
GPUComputePipeline* createComputePipeline(
const GPUComputePipelineDescriptor* descriptor,
ExceptionState& exception_state);
ScriptPromise createRenderPipelineAsync(
ScriptState* script_state,
const GPURenderPipelineDescriptor* descriptor);
ScriptPromise createComputePipelineAsync(
ScriptState* script_state,
const GPUComputePipelineDescriptor* descriptor);
GPUCommandEncoder* createCommandEncoder(
const GPUCommandEncoderDescriptor* descriptor);
GPURenderBundleEncoder* createRenderBundleEncoder(
const GPURenderBundleEncoderDescriptor* descriptor,
ExceptionState& exception_state);
GPUQuerySet* createQuerySet(const GPUQuerySetDescriptor* descriptor,
ExceptionState& exception_state);
void pushErrorScope(const V8GPUErrorFilter& filter);
ScriptPromise popErrorScope(ScriptState* script_state);
DEFINE_ATTRIBUTE_EVENT_LISTENER(uncapturederror, kUncapturederror)
// EventTarget overrides.
const AtomicString& InterfaceName() const override;
ExecutionContext* GetExecutionContext() const override;
void InjectError(WGPUErrorType type, const char* message);
void AddConsoleWarning(const String& message);
void AddConsoleWarning(const char* message);
void AddSingletonWarning(GPUSingletonWarning type);
void TrackTextureWithMailbox(GPUTexture* texture);
void UntrackTextureWithMailbox(GPUTexture* texture);
bool ValidateTextureFormatUsage(V8GPUTextureFormat format,
ExceptionState& exception_state);
std::string formattedLabel() const;
// Store the buffer in a weak hash set so we can unmap it when the
// device is destroyed.
void TrackMappableBuffer(GPUBuffer* buffer);
// Untrack the GPUBuffer. This is called eagerly when the buffer is
// destroyed.
void UntrackMappableBuffer(GPUBuffer* buffer);
private:
using LostProperty =
ScriptPromiseProperty<Member<GPUDeviceLostInfo>, ToV8UndefinedGenerator>;
// Used by USING_PRE_FINALIZER.
void Dispose();
void DissociateMailboxes();
void UnmapAllMappableBuffers(v8::Isolate* isolate);
void OnUncapturedError(WGPUErrorType errorType, const char* message);
void OnLogging(WGPULoggingType loggingType, const char* message);
void OnDeviceLostError(WGPUDeviceLostReason, const char* message);
void OnPopErrorScopeCallback(ScriptPromiseResolver* resolver,
WGPUErrorType type,
const char* message);
void OnCreateRenderPipelineAsyncCallback(ScriptPromiseResolver* resolver,
absl::optional<String> label,
WGPUCreatePipelineAsyncStatus status,
WGPURenderPipeline render_pipeline,
const char* message);
void OnCreateComputePipelineAsyncCallback(
ScriptPromiseResolver* resolver,
absl::optional<String> label,
WGPUCreatePipelineAsyncStatus status,
WGPUComputePipeline compute_pipeline,
const char* message);
void setLabelImpl(const String& value) override {
std::string utf8_label = value.Utf8();
GetProcs().deviceSetLabel(GetHandle(), utf8_label.c_str());
}
Member<GPUAdapter> adapter_;
Member<GPUSupportedFeatures> features_;
Member<GPUSupportedLimits> limits_;
Member<GPUQueue> queue_;
Member<LostProperty> lost_property_;
std::unique_ptr<WGPURepeatingCallback<void(WGPUErrorType, const char*)>>
error_callback_;
std::unique_ptr<WGPURepeatingCallback<void(WGPULoggingType, const char*)>>
logging_callback_;
// lost_callback_ is stored as a unique_ptr since it may never be called.
// We need to be sure to free it on deletion of the device.
// Inside OnDeviceLostError we'll release the unique_ptr to avoid a double
// free.
std::unique_ptr<
WGPURepeatingCallback<void(WGPUDeviceLostReason, const char*)>>
lost_callback_;
static constexpr int kMaxAllowedConsoleWarnings = 500;
int allowed_console_warnings_remaining_ = kMaxAllowedConsoleWarnings;
// Textures with mailboxes that should be dissociated before device.destroy().
HeapHashSet<WeakMember<GPUTexture>> textures_with_mailbox_;
HeapHashSet<WeakMember<GPUBuffer>> mappable_buffers_;
Member<ExternalTextureCache> external_texture_cache_;
std::bitset<static_cast<size_t>(GPUSingletonWarning::kCount)>
singleton_warning_fired_;
// This attribute records that whether GPUDevice is destroyed (via destroy()).
bool destroyed_ = false;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_DEVICE_H_