mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-05-15 03:41:34 +00:00
Unlike API objects, the AttachmentState object is only used internally and should have no external references. We should not increment the reference count on creation because it is Ref'ed internally. This patch also adds ASSERTs that all Device caches are empty when the Device is destroyed. Bug: dawn:154 Change-Id: I5dd46bde03c0be920356444e6b1214ed38e833e8 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/9761 Commit-Queue: Kai Ninomiya <kainino@chromium.org> Reviewed-by: Kai Ninomiya <kainino@chromium.org>
664 lines
24 KiB
C++
664 lines
24 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.
|
|
|
|
#include "dawn_native/Device.h"
|
|
|
|
#include "dawn_native/Adapter.h"
|
|
#include "dawn_native/AttachmentState.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/DynamicUploader.h"
|
|
#include "dawn_native/ErrorData.h"
|
|
#include "dawn_native/Fence.h"
|
|
#include "dawn_native/FenceSignalTracker.h"
|
|
#include "dawn_native/Instance.h"
|
|
#include "dawn_native/PipelineLayout.h"
|
|
#include "dawn_native/Queue.h"
|
|
#include "dawn_native/RenderPipeline.h"
|
|
#include "dawn_native/Sampler.h"
|
|
#include "dawn_native/ShaderModule.h"
|
|
#include "dawn_native/SwapChain.h"
|
|
#include "dawn_native/Texture.h"
|
|
|
|
#include <unordered_set>
|
|
|
|
namespace dawn_native {
|
|
|
|
// DeviceBase::Caches
|
|
|
|
// The caches are unordered_sets of pointers with special hash and compare functions
|
|
// to compare the value of the objects, instead of the pointers.
|
|
template <typename Object>
|
|
using ContentLessObjectCache =
|
|
std::unordered_set<Object*, typename Object::HashFunc, typename Object::EqualityFunc>;
|
|
|
|
struct DeviceBase::Caches {
|
|
ContentLessObjectCache<AttachmentStateBlueprint> attachmentStates;
|
|
ContentLessObjectCache<BindGroupLayoutBase> bindGroupLayouts;
|
|
ContentLessObjectCache<ComputePipelineBase> computePipelines;
|
|
ContentLessObjectCache<PipelineLayoutBase> pipelineLayouts;
|
|
ContentLessObjectCache<RenderPipelineBase> renderPipelines;
|
|
ContentLessObjectCache<SamplerBase> samplers;
|
|
ContentLessObjectCache<ShaderModuleBase> shaderModules;
|
|
};
|
|
|
|
// DeviceBase
|
|
|
|
DeviceBase::DeviceBase(AdapterBase* adapter, const DeviceDescriptor* descriptor)
|
|
: mAdapter(adapter) {
|
|
mCaches = std::make_unique<DeviceBase::Caches>();
|
|
mFenceSignalTracker = std::make_unique<FenceSignalTracker>(this);
|
|
mDynamicUploader = std::make_unique<DynamicUploader>(this);
|
|
SetDefaultToggles();
|
|
|
|
if (descriptor != nullptr) {
|
|
ApplyExtensions(descriptor);
|
|
}
|
|
|
|
mFormatTable = BuildFormatTable(this);
|
|
}
|
|
|
|
DeviceBase::~DeviceBase() {
|
|
// Devices must explicitly free the uploader
|
|
ASSERT(mDynamicUploader == nullptr);
|
|
ASSERT(mDeferredCreateBufferMappedAsyncResults.empty());
|
|
|
|
ASSERT(mCaches->attachmentStates.empty());
|
|
ASSERT(mCaches->bindGroupLayouts.empty());
|
|
ASSERT(mCaches->computePipelines.empty());
|
|
ASSERT(mCaches->pipelineLayouts.empty());
|
|
ASSERT(mCaches->renderPipelines.empty());
|
|
ASSERT(mCaches->samplers.empty());
|
|
ASSERT(mCaches->shaderModules.empty());
|
|
}
|
|
|
|
void DeviceBase::HandleError(const char* message) {
|
|
if (mErrorCallback) {
|
|
mErrorCallback(message, mErrorUserdata);
|
|
}
|
|
}
|
|
|
|
void DeviceBase::SetErrorCallback(dawn::DeviceErrorCallback callback, void* userdata) {
|
|
mErrorCallback = callback;
|
|
mErrorUserdata = userdata;
|
|
}
|
|
|
|
MaybeError DeviceBase::ValidateObject(const ObjectBase* object) const {
|
|
if (DAWN_UNLIKELY(object->GetDevice() != this)) {
|
|
return DAWN_VALIDATION_ERROR("Object from a different device.");
|
|
}
|
|
if (DAWN_UNLIKELY(object->IsError())) {
|
|
return DAWN_VALIDATION_ERROR("Object is an error.");
|
|
}
|
|
return {};
|
|
}
|
|
|
|
AdapterBase* DeviceBase::GetAdapter() const {
|
|
return mAdapter;
|
|
}
|
|
|
|
FenceSignalTracker* DeviceBase::GetFenceSignalTracker() const {
|
|
return mFenceSignalTracker.get();
|
|
}
|
|
|
|
ResultOrError<const Format*> DeviceBase::GetInternalFormat(dawn::TextureFormat format) const {
|
|
size_t index = ComputeFormatIndex(format);
|
|
if (index >= mFormatTable.size()) {
|
|
return DAWN_VALIDATION_ERROR("Unknown texture format");
|
|
}
|
|
|
|
const Format* internalFormat = &mFormatTable[index];
|
|
if (!internalFormat->isSupported) {
|
|
return DAWN_VALIDATION_ERROR("Unsupported texture format");
|
|
}
|
|
|
|
return internalFormat;
|
|
}
|
|
|
|
const Format& DeviceBase::GetValidInternalFormat(dawn::TextureFormat format) const {
|
|
size_t index = ComputeFormatIndex(format);
|
|
ASSERT(index < mFormatTable.size());
|
|
ASSERT(mFormatTable[index].isSupported);
|
|
return mFormatTable[index];
|
|
}
|
|
|
|
ResultOrError<BindGroupLayoutBase*> DeviceBase::GetOrCreateBindGroupLayout(
|
|
const BindGroupLayoutDescriptor* descriptor) {
|
|
BindGroupLayoutBase blueprint(this, descriptor, true);
|
|
|
|
auto iter = mCaches->bindGroupLayouts.find(&blueprint);
|
|
if (iter != mCaches->bindGroupLayouts.end()) {
|
|
(*iter)->Reference();
|
|
return *iter;
|
|
}
|
|
|
|
BindGroupLayoutBase* backendObj;
|
|
DAWN_TRY_ASSIGN(backendObj, CreateBindGroupLayoutImpl(descriptor));
|
|
mCaches->bindGroupLayouts.insert(backendObj);
|
|
return backendObj;
|
|
}
|
|
|
|
void DeviceBase::UncacheBindGroupLayout(BindGroupLayoutBase* obj) {
|
|
size_t removedCount = mCaches->bindGroupLayouts.erase(obj);
|
|
ASSERT(removedCount == 1);
|
|
}
|
|
|
|
ResultOrError<ComputePipelineBase*> DeviceBase::GetOrCreateComputePipeline(
|
|
const ComputePipelineDescriptor* descriptor) {
|
|
ComputePipelineBase blueprint(this, descriptor, true);
|
|
|
|
auto iter = mCaches->computePipelines.find(&blueprint);
|
|
if (iter != mCaches->computePipelines.end()) {
|
|
(*iter)->Reference();
|
|
return *iter;
|
|
}
|
|
|
|
ComputePipelineBase* backendObj;
|
|
DAWN_TRY_ASSIGN(backendObj, CreateComputePipelineImpl(descriptor));
|
|
mCaches->computePipelines.insert(backendObj);
|
|
return backendObj;
|
|
}
|
|
|
|
void DeviceBase::UncacheComputePipeline(ComputePipelineBase* obj) {
|
|
size_t removedCount = mCaches->computePipelines.erase(obj);
|
|
ASSERT(removedCount == 1);
|
|
}
|
|
|
|
ResultOrError<PipelineLayoutBase*> DeviceBase::GetOrCreatePipelineLayout(
|
|
const PipelineLayoutDescriptor* descriptor) {
|
|
PipelineLayoutBase blueprint(this, descriptor, true);
|
|
|
|
auto iter = mCaches->pipelineLayouts.find(&blueprint);
|
|
if (iter != mCaches->pipelineLayouts.end()) {
|
|
(*iter)->Reference();
|
|
return *iter;
|
|
}
|
|
|
|
PipelineLayoutBase* backendObj;
|
|
DAWN_TRY_ASSIGN(backendObj, CreatePipelineLayoutImpl(descriptor));
|
|
mCaches->pipelineLayouts.insert(backendObj);
|
|
return backendObj;
|
|
}
|
|
|
|
void DeviceBase::UncachePipelineLayout(PipelineLayoutBase* obj) {
|
|
size_t removedCount = mCaches->pipelineLayouts.erase(obj);
|
|
ASSERT(removedCount == 1);
|
|
}
|
|
|
|
ResultOrError<RenderPipelineBase*> DeviceBase::GetOrCreateRenderPipeline(
|
|
const RenderPipelineDescriptor* descriptor) {
|
|
RenderPipelineBase blueprint(this, descriptor, true);
|
|
|
|
auto iter = mCaches->renderPipelines.find(&blueprint);
|
|
if (iter != mCaches->renderPipelines.end()) {
|
|
(*iter)->Reference();
|
|
return *iter;
|
|
}
|
|
|
|
RenderPipelineBase* backendObj;
|
|
DAWN_TRY_ASSIGN(backendObj, CreateRenderPipelineImpl(descriptor));
|
|
mCaches->renderPipelines.insert(backendObj);
|
|
return backendObj;
|
|
}
|
|
|
|
void DeviceBase::UncacheRenderPipeline(RenderPipelineBase* obj) {
|
|
size_t removedCount = mCaches->renderPipelines.erase(obj);
|
|
ASSERT(removedCount == 1);
|
|
}
|
|
|
|
ResultOrError<SamplerBase*> DeviceBase::GetOrCreateSampler(
|
|
const SamplerDescriptor* descriptor) {
|
|
SamplerBase blueprint(this, descriptor, true);
|
|
|
|
auto iter = mCaches->samplers.find(&blueprint);
|
|
if (iter != mCaches->samplers.end()) {
|
|
(*iter)->Reference();
|
|
return *iter;
|
|
}
|
|
|
|
SamplerBase* backendObj;
|
|
DAWN_TRY_ASSIGN(backendObj, CreateSamplerImpl(descriptor));
|
|
mCaches->samplers.insert(backendObj);
|
|
return backendObj;
|
|
}
|
|
|
|
void DeviceBase::UncacheSampler(SamplerBase* obj) {
|
|
size_t removedCount = mCaches->samplers.erase(obj);
|
|
ASSERT(removedCount == 1);
|
|
}
|
|
|
|
ResultOrError<ShaderModuleBase*> DeviceBase::GetOrCreateShaderModule(
|
|
const ShaderModuleDescriptor* descriptor) {
|
|
ShaderModuleBase blueprint(this, descriptor, true);
|
|
|
|
auto iter = mCaches->shaderModules.find(&blueprint);
|
|
if (iter != mCaches->shaderModules.end()) {
|
|
(*iter)->Reference();
|
|
return *iter;
|
|
}
|
|
|
|
ShaderModuleBase* backendObj;
|
|
DAWN_TRY_ASSIGN(backendObj, CreateShaderModuleImpl(descriptor));
|
|
mCaches->shaderModules.insert(backendObj);
|
|
return backendObj;
|
|
}
|
|
|
|
void DeviceBase::UncacheShaderModule(ShaderModuleBase* obj) {
|
|
size_t removedCount = mCaches->shaderModules.erase(obj);
|
|
ASSERT(removedCount == 1);
|
|
}
|
|
|
|
Ref<AttachmentState> DeviceBase::GetOrCreateAttachmentState(
|
|
const RenderPipelineDescriptor* descriptor) {
|
|
AttachmentStateBlueprint blueprint(descriptor);
|
|
|
|
auto iter = mCaches->attachmentStates.find(&blueprint);
|
|
if (iter != mCaches->attachmentStates.end()) {
|
|
return static_cast<AttachmentState*>(*iter);
|
|
}
|
|
|
|
Ref<AttachmentState> attachmentState = new AttachmentState(this, blueprint);
|
|
attachmentState->Release();
|
|
mCaches->attachmentStates.insert(attachmentState.Get());
|
|
return attachmentState;
|
|
}
|
|
|
|
Ref<AttachmentState> DeviceBase::GetOrCreateAttachmentState(
|
|
const RenderPassDescriptor* descriptor) {
|
|
AttachmentStateBlueprint blueprint(descriptor);
|
|
|
|
auto iter = mCaches->attachmentStates.find(&blueprint);
|
|
if (iter != mCaches->attachmentStates.end()) {
|
|
return static_cast<AttachmentState*>(*iter);
|
|
}
|
|
|
|
Ref<AttachmentState> attachmentState = new AttachmentState(this, blueprint);
|
|
attachmentState->Release();
|
|
mCaches->attachmentStates.insert(attachmentState.Get());
|
|
return attachmentState;
|
|
}
|
|
|
|
void DeviceBase::UncacheAttachmentState(AttachmentState* obj) {
|
|
size_t removedCount = mCaches->attachmentStates.erase(obj);
|
|
ASSERT(removedCount == 1);
|
|
}
|
|
|
|
// Object creation API methods
|
|
|
|
BindGroupBase* DeviceBase::CreateBindGroup(const BindGroupDescriptor* descriptor) {
|
|
BindGroupBase* result = nullptr;
|
|
|
|
if (ConsumedError(CreateBindGroupInternal(&result, descriptor))) {
|
|
return BindGroupBase::MakeError(this);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
BindGroupLayoutBase* DeviceBase::CreateBindGroupLayout(
|
|
const BindGroupLayoutDescriptor* descriptor) {
|
|
BindGroupLayoutBase* result = nullptr;
|
|
|
|
if (ConsumedError(CreateBindGroupLayoutInternal(&result, descriptor))) {
|
|
return BindGroupLayoutBase::MakeError(this);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
BufferBase* DeviceBase::CreateBuffer(const BufferDescriptor* descriptor) {
|
|
BufferBase* result = nullptr;
|
|
|
|
if (ConsumedError(CreateBufferInternal(&result, descriptor))) {
|
|
return BufferBase::MakeError(this);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
DawnCreateBufferMappedResult DeviceBase::CreateBufferMapped(
|
|
const BufferDescriptor* descriptor) {
|
|
BufferBase* buffer = nullptr;
|
|
uint8_t* data = nullptr;
|
|
|
|
uint64_t size = descriptor->size;
|
|
if (ConsumedError(CreateBufferInternal(&buffer, descriptor)) ||
|
|
ConsumedError(buffer->MapAtCreation(&data))) {
|
|
// Map failed. Replace the buffer with an error buffer.
|
|
if (buffer != nullptr) {
|
|
delete buffer;
|
|
}
|
|
buffer = BufferBase::MakeErrorMapped(this, size, &data);
|
|
}
|
|
|
|
ASSERT(buffer != nullptr);
|
|
if (data == nullptr) {
|
|
// |data| may be nullptr if there was an OOM in MakeErrorMapped.
|
|
// Non-zero dataLength and nullptr data is used to indicate there should be
|
|
// mapped data but the allocation failed.
|
|
ASSERT(buffer->IsError());
|
|
} else {
|
|
memset(data, 0, size);
|
|
}
|
|
|
|
DawnCreateBufferMappedResult result = {};
|
|
result.buffer = reinterpret_cast<DawnBuffer>(buffer);
|
|
result.data = data;
|
|
result.dataLength = size;
|
|
|
|
return result;
|
|
}
|
|
void DeviceBase::CreateBufferMappedAsync(const BufferDescriptor* descriptor,
|
|
dawn::BufferCreateMappedCallback callback,
|
|
void* userdata) {
|
|
DawnCreateBufferMappedResult result = CreateBufferMapped(descriptor);
|
|
|
|
DawnBufferMapAsyncStatus status = DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS;
|
|
if (result.data == nullptr || result.dataLength != descriptor->size) {
|
|
status = DAWN_BUFFER_MAP_ASYNC_STATUS_ERROR;
|
|
}
|
|
|
|
DeferredCreateBufferMappedAsync deferred_info;
|
|
deferred_info.callback = callback;
|
|
deferred_info.status = status;
|
|
deferred_info.result = result;
|
|
deferred_info.userdata = userdata;
|
|
|
|
// The callback is deferred so it matches the async behavior of WebGPU.
|
|
mDeferredCreateBufferMappedAsyncResults.push_back(deferred_info);
|
|
}
|
|
CommandEncoderBase* DeviceBase::CreateCommandEncoder(
|
|
const CommandEncoderDescriptor* descriptor) {
|
|
return new CommandEncoderBase(this, descriptor);
|
|
}
|
|
ComputePipelineBase* DeviceBase::CreateComputePipeline(
|
|
const ComputePipelineDescriptor* descriptor) {
|
|
ComputePipelineBase* result = nullptr;
|
|
|
|
if (ConsumedError(CreateComputePipelineInternal(&result, descriptor))) {
|
|
return ComputePipelineBase::MakeError(this);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
PipelineLayoutBase* DeviceBase::CreatePipelineLayout(
|
|
const PipelineLayoutDescriptor* descriptor) {
|
|
PipelineLayoutBase* result = nullptr;
|
|
|
|
if (ConsumedError(CreatePipelineLayoutInternal(&result, descriptor))) {
|
|
return PipelineLayoutBase::MakeError(this);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
QueueBase* DeviceBase::CreateQueue() {
|
|
QueueBase* result = nullptr;
|
|
|
|
if (ConsumedError(CreateQueueInternal(&result))) {
|
|
// If queue creation failure ever becomes possible, we should implement MakeError and
|
|
// friends for them.
|
|
UNREACHABLE();
|
|
return nullptr;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
SamplerBase* DeviceBase::CreateSampler(const SamplerDescriptor* descriptor) {
|
|
SamplerBase* result = nullptr;
|
|
|
|
if (ConsumedError(CreateSamplerInternal(&result, descriptor))) {
|
|
return SamplerBase::MakeError(this);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
RenderPipelineBase* DeviceBase::CreateRenderPipeline(
|
|
const RenderPipelineDescriptor* descriptor) {
|
|
RenderPipelineBase* result = nullptr;
|
|
|
|
if (ConsumedError(CreateRenderPipelineInternal(&result, descriptor))) {
|
|
return RenderPipelineBase::MakeError(this);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
ShaderModuleBase* DeviceBase::CreateShaderModule(const ShaderModuleDescriptor* descriptor) {
|
|
ShaderModuleBase* result = nullptr;
|
|
|
|
if (ConsumedError(CreateShaderModuleInternal(&result, descriptor))) {
|
|
return ShaderModuleBase::MakeError(this);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
SwapChainBase* DeviceBase::CreateSwapChain(const SwapChainDescriptor* descriptor) {
|
|
SwapChainBase* result = nullptr;
|
|
|
|
if (ConsumedError(CreateSwapChainInternal(&result, descriptor))) {
|
|
return SwapChainBase::MakeError(this);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
TextureBase* DeviceBase::CreateTexture(const TextureDescriptor* descriptor) {
|
|
TextureBase* result = nullptr;
|
|
|
|
if (ConsumedError(CreateTextureInternal(&result, descriptor))) {
|
|
return TextureBase::MakeError(this);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
TextureViewBase* DeviceBase::CreateTextureView(TextureBase* texture,
|
|
const TextureViewDescriptor* descriptor) {
|
|
TextureViewBase* result = nullptr;
|
|
|
|
if (ConsumedError(CreateTextureViewInternal(&result, texture, descriptor))) {
|
|
return TextureViewBase::MakeError(this);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
// Other Device API methods
|
|
|
|
void DeviceBase::Tick() {
|
|
TickImpl();
|
|
{
|
|
auto deferredResults = std::move(mDeferredCreateBufferMappedAsyncResults);
|
|
for (const auto& deferred : deferredResults) {
|
|
deferred.callback(deferred.status, deferred.result, deferred.userdata);
|
|
}
|
|
}
|
|
mFenceSignalTracker->Tick(GetCompletedCommandSerial());
|
|
}
|
|
|
|
void DeviceBase::Reference() {
|
|
ASSERT(mRefCount != 0);
|
|
mRefCount++;
|
|
}
|
|
|
|
void DeviceBase::Release() {
|
|
ASSERT(mRefCount != 0);
|
|
mRefCount--;
|
|
if (mRefCount == 0) {
|
|
delete this;
|
|
}
|
|
}
|
|
|
|
void DeviceBase::ApplyToggleOverrides(const DeviceDescriptor* deviceDescriptor) {
|
|
ASSERT(deviceDescriptor);
|
|
|
|
for (const char* toggleName : deviceDescriptor->forceEnabledToggles) {
|
|
Toggle toggle = GetAdapter()->GetInstance()->ToggleNameToEnum(toggleName);
|
|
if (toggle != Toggle::InvalidEnum) {
|
|
mTogglesSet.SetToggle(toggle, true);
|
|
}
|
|
}
|
|
for (const char* toggleName : deviceDescriptor->forceDisabledToggles) {
|
|
Toggle toggle = GetAdapter()->GetInstance()->ToggleNameToEnum(toggleName);
|
|
if (toggle != Toggle::InvalidEnum) {
|
|
mTogglesSet.SetToggle(toggle, false);
|
|
}
|
|
}
|
|
}
|
|
|
|
void DeviceBase::ApplyExtensions(const DeviceDescriptor* deviceDescriptor) {
|
|
ASSERT(deviceDescriptor);
|
|
ASSERT(GetAdapter()->SupportsAllRequestedExtensions(deviceDescriptor->requiredExtensions));
|
|
|
|
mEnabledExtensions = GetAdapter()->GetInstance()->ExtensionNamesToExtensionsSet(
|
|
deviceDescriptor->requiredExtensions);
|
|
}
|
|
|
|
std::vector<const char*> DeviceBase::GetEnabledExtensions() const {
|
|
return mEnabledExtensions.GetEnabledExtensionNames();
|
|
}
|
|
|
|
std::vector<const char*> DeviceBase::GetTogglesUsed() const {
|
|
return mTogglesSet.GetEnabledToggleNames();
|
|
}
|
|
|
|
bool DeviceBase::IsExtensionEnabled(Extension extension) const {
|
|
return mEnabledExtensions.IsEnabled(extension);
|
|
}
|
|
|
|
bool DeviceBase::IsToggleEnabled(Toggle toggle) const {
|
|
return mTogglesSet.IsEnabled(toggle);
|
|
}
|
|
|
|
size_t DeviceBase::GetLazyClearCountForTesting() {
|
|
return mLazyClearCountForTesting;
|
|
}
|
|
|
|
void DeviceBase::IncrementLazyClearCountForTesting() {
|
|
++mLazyClearCountForTesting;
|
|
}
|
|
|
|
void DeviceBase::SetDefaultToggles() {
|
|
// Sets the default-enabled toggles
|
|
mTogglesSet.SetToggle(Toggle::LazyClearResourceOnFirstUse, true);
|
|
}
|
|
|
|
// Implementation details of object creation
|
|
|
|
MaybeError DeviceBase::CreateBindGroupInternal(BindGroupBase** result,
|
|
const BindGroupDescriptor* descriptor) {
|
|
DAWN_TRY(ValidateBindGroupDescriptor(this, descriptor));
|
|
DAWN_TRY_ASSIGN(*result, CreateBindGroupImpl(descriptor));
|
|
return {};
|
|
}
|
|
|
|
MaybeError DeviceBase::CreateBindGroupLayoutInternal(
|
|
BindGroupLayoutBase** result,
|
|
const BindGroupLayoutDescriptor* descriptor) {
|
|
DAWN_TRY(ValidateBindGroupLayoutDescriptor(this, descriptor));
|
|
DAWN_TRY_ASSIGN(*result, GetOrCreateBindGroupLayout(descriptor));
|
|
return {};
|
|
}
|
|
|
|
MaybeError DeviceBase::CreateBufferInternal(BufferBase** result,
|
|
const BufferDescriptor* descriptor) {
|
|
DAWN_TRY(ValidateBufferDescriptor(this, descriptor));
|
|
DAWN_TRY_ASSIGN(*result, CreateBufferImpl(descriptor));
|
|
return {};
|
|
}
|
|
|
|
MaybeError DeviceBase::CreateComputePipelineInternal(
|
|
ComputePipelineBase** result,
|
|
const ComputePipelineDescriptor* descriptor) {
|
|
DAWN_TRY(ValidateComputePipelineDescriptor(this, descriptor));
|
|
DAWN_TRY_ASSIGN(*result, GetOrCreateComputePipeline(descriptor));
|
|
return {};
|
|
}
|
|
|
|
MaybeError DeviceBase::CreatePipelineLayoutInternal(
|
|
PipelineLayoutBase** result,
|
|
const PipelineLayoutDescriptor* descriptor) {
|
|
DAWN_TRY(ValidatePipelineLayoutDescriptor(this, descriptor));
|
|
DAWN_TRY_ASSIGN(*result, GetOrCreatePipelineLayout(descriptor));
|
|
return {};
|
|
}
|
|
|
|
MaybeError DeviceBase::CreateQueueInternal(QueueBase** result) {
|
|
DAWN_TRY_ASSIGN(*result, CreateQueueImpl());
|
|
return {};
|
|
}
|
|
|
|
MaybeError DeviceBase::CreateRenderPipelineInternal(
|
|
RenderPipelineBase** result,
|
|
const RenderPipelineDescriptor* descriptor) {
|
|
DAWN_TRY(ValidateRenderPipelineDescriptor(this, descriptor));
|
|
DAWN_TRY_ASSIGN(*result, GetOrCreateRenderPipeline(descriptor));
|
|
return {};
|
|
}
|
|
|
|
MaybeError DeviceBase::CreateSamplerInternal(SamplerBase** result,
|
|
const SamplerDescriptor* descriptor) {
|
|
DAWN_TRY(ValidateSamplerDescriptor(this, descriptor));
|
|
DAWN_TRY_ASSIGN(*result, GetOrCreateSampler(descriptor));
|
|
return {};
|
|
}
|
|
|
|
MaybeError DeviceBase::CreateShaderModuleInternal(ShaderModuleBase** result,
|
|
const ShaderModuleDescriptor* descriptor) {
|
|
DAWN_TRY(ValidateShaderModuleDescriptor(this, descriptor));
|
|
DAWN_TRY_ASSIGN(*result, GetOrCreateShaderModule(descriptor));
|
|
return {};
|
|
}
|
|
|
|
MaybeError DeviceBase::CreateSwapChainInternal(SwapChainBase** result,
|
|
const SwapChainDescriptor* descriptor) {
|
|
DAWN_TRY(ValidateSwapChainDescriptor(this, descriptor));
|
|
DAWN_TRY_ASSIGN(*result, CreateSwapChainImpl(descriptor));
|
|
return {};
|
|
}
|
|
|
|
MaybeError DeviceBase::CreateTextureInternal(TextureBase** result,
|
|
const TextureDescriptor* descriptor) {
|
|
DAWN_TRY(ValidateTextureDescriptor(this, descriptor));
|
|
DAWN_TRY_ASSIGN(*result, CreateTextureImpl(descriptor));
|
|
return {};
|
|
}
|
|
|
|
MaybeError DeviceBase::CreateTextureViewInternal(TextureViewBase** result,
|
|
TextureBase* texture,
|
|
const TextureViewDescriptor* descriptor) {
|
|
DAWN_TRY(ValidateTextureViewDescriptor(this, texture, descriptor));
|
|
DAWN_TRY_ASSIGN(*result, CreateTextureViewImpl(texture, descriptor));
|
|
return {};
|
|
}
|
|
|
|
// Other implementation details
|
|
|
|
void DeviceBase::ConsumeError(ErrorData* error) {
|
|
ASSERT(error != nullptr);
|
|
HandleError(error->GetMessage().c_str());
|
|
delete error;
|
|
}
|
|
|
|
ResultOrError<DynamicUploader*> DeviceBase::GetDynamicUploader() const {
|
|
if (mDynamicUploader->IsEmpty()) {
|
|
DAWN_TRY(mDynamicUploader->CreateAndAppendBuffer());
|
|
}
|
|
return mDynamicUploader.get();
|
|
}
|
|
|
|
void DeviceBase::SetToggle(Toggle toggle, bool isEnabled) {
|
|
mTogglesSet.SetToggle(toggle, isEnabled);
|
|
}
|
|
|
|
} // namespace dawn_native
|