DeviceBase: Add helper to consume errors

This adds DeviceBase::ConsumedError which is a helper method intended to
be the main place where Error.h errors are consumed.

To test this mechanism, object creation using descriptors is changed to
use ConsumedError, which finally gets their validation errors go
somewhere. This mechanism isn't final though because we have yet to
implement WebGPU error handling.
This commit is contained in:
Corentin Wallez 2018-07-16 17:40:08 +02:00 committed by Corentin Wallez
parent 629c11baad
commit 52f2383bb8
3 changed files with 78 additions and 40 deletions

View File

@ -88,7 +88,7 @@ namespace backend {
} }
BindGroupLayoutBase::~BindGroupLayoutBase() { BindGroupLayoutBase::~BindGroupLayoutBase() {
// Do not register the actual cached object if we are a blueprint // Do not uncache the actual cached object if we are a blueprint
if (!mIsBlueprint) { if (!mIsBlueprint) {
mDevice->UncacheBindGroupLayout(this); mDevice->UncacheBindGroupLayout(this);
} }

View File

@ -93,25 +93,20 @@ namespace backend {
mCaches->bindGroupLayouts.erase(obj); mCaches->bindGroupLayouts.erase(obj);
} }
// Object creation API methods
BindGroupBuilder* DeviceBase::CreateBindGroupBuilder() { BindGroupBuilder* DeviceBase::CreateBindGroupBuilder() {
return new BindGroupBuilder(this); return new BindGroupBuilder(this);
} }
BindGroupLayoutBase* DeviceBase::CreateBindGroupLayout( BindGroupLayoutBase* DeviceBase::CreateBindGroupLayout(
const nxt::BindGroupLayoutDescriptor* descriptor) { const nxt::BindGroupLayoutDescriptor* descriptor) {
MaybeError validation = ValidateBindGroupLayoutDescriptor(this, descriptor); BindGroupLayoutBase* result = nullptr;
if (validation.IsError()) {
// TODO(cwallez@chromium.org): Implement the WebGPU error handling mechanism. if (ConsumedError(CreateBindGroupLayoutInternal(&result, descriptor))) {
delete validation.AcquireError();
return nullptr; return nullptr;
} }
auto maybeBindGroupLayout = GetOrCreateBindGroupLayout(descriptor); return result;
if (maybeBindGroupLayout.IsError()) {
// TODO(cwallez@chromium.org): Implement the WebGPU error handling mechanism.
delete maybeBindGroupLayout.AcquireError();
return nullptr;
}
return maybeBindGroupLayout.AcquireSuccess();
} }
BlendStateBuilder* DeviceBase::CreateBlendStateBuilder() { BlendStateBuilder* DeviceBase::CreateBlendStateBuilder() {
return new BlendStateBuilder(this); return new BlendStateBuilder(this);
@ -133,30 +128,22 @@ namespace backend {
} }
PipelineLayoutBase* DeviceBase::CreatePipelineLayout( PipelineLayoutBase* DeviceBase::CreatePipelineLayout(
const nxt::PipelineLayoutDescriptor* descriptor) { const nxt::PipelineLayoutDescriptor* descriptor) {
MaybeError validation = ValidatePipelineLayoutDescriptor(this, descriptor); PipelineLayoutBase* result = nullptr;
if (validation.IsError()) {
// TODO(cwallez@chromium.org): Implement the WebGPU error handling mechanism. if (ConsumedError(CreatePipelineLayoutInternal(&result, descriptor))) {
delete validation.AcquireError();
return nullptr; return nullptr;
} }
ResultOrError<PipelineLayoutBase*> maybePipelineLayout = return result;
CreatePipelineLayoutImpl(descriptor);
if (maybePipelineLayout.IsError()) {
// TODO(cwallez@chromium.org): Implement the WebGPU error handling mechanism.
delete maybePipelineLayout.AcquireError();
return nullptr;
}
return maybePipelineLayout.AcquireSuccess();
} }
QueueBase* DeviceBase::CreateQueue() { QueueBase* DeviceBase::CreateQueue() {
ResultOrError<QueueBase*> maybeQueue = CreateQueueImpl(); QueueBase* result = nullptr;
if (maybeQueue.IsError()) {
// TODO(cwallez@chromium.org): Implement the WebGPU error handling mechanism. if (ConsumedError(CreateQueueInternal(&result))) {
delete maybeQueue.AcquireError();
return nullptr; return nullptr;
} }
return maybeQueue.AcquireSuccess();
return result;
} }
RenderPassDescriptorBuilder* DeviceBase::CreateRenderPassDescriptorBuilder() { RenderPassDescriptorBuilder* DeviceBase::CreateRenderPassDescriptorBuilder() {
return new RenderPassDescriptorBuilder(this); return new RenderPassDescriptorBuilder(this);
@ -165,20 +152,13 @@ namespace backend {
return new RenderPipelineBuilder(this); return new RenderPipelineBuilder(this);
} }
SamplerBase* DeviceBase::CreateSampler(const nxt::SamplerDescriptor* descriptor) { SamplerBase* DeviceBase::CreateSampler(const nxt::SamplerDescriptor* descriptor) {
MaybeError validation = ValidateSamplerDescriptor(this, descriptor); SamplerBase* result = nullptr;
if (validation.IsError()) {
// TODO(cwallez@chromium.org): Implement the WebGPU error handling mechanism. if (ConsumedError(CreateSamplerInternal(&result, descriptor))) {
delete validation.AcquireError();
return nullptr; return nullptr;
} }
ResultOrError<SamplerBase*> maybeSampler = CreateSamplerImpl(descriptor); return result;
if (maybeSampler.IsError()) {
// TODO(cwallez@chromium.org): Implement the WebGPU error handling mechanism.
delete maybeSampler.AcquireError();
return nullptr;
}
return maybeSampler.AcquireSuccess();
} }
ShaderModuleBuilder* DeviceBase::CreateShaderModuleBuilder() { ShaderModuleBuilder* DeviceBase::CreateShaderModuleBuilder() {
return new ShaderModuleBuilder(this); return new ShaderModuleBuilder(this);
@ -190,6 +170,8 @@ namespace backend {
return new TextureBuilder(this); return new TextureBuilder(this);
} }
// Other Device API methods
void DeviceBase::Tick() { void DeviceBase::Tick() {
TickImpl(); TickImpl();
} }
@ -207,4 +189,42 @@ namespace backend {
} }
} }
// Implementation details of object creation
MaybeError DeviceBase::CreateBindGroupLayoutInternal(
BindGroupLayoutBase** result,
const nxt::BindGroupLayoutDescriptor* descriptor) {
NXT_TRY(ValidateBindGroupLayoutDescriptor(this, descriptor));
NXT_TRY_ASSIGN(*result, GetOrCreateBindGroupLayout(descriptor));
return {};
}
MaybeError DeviceBase::CreatePipelineLayoutInternal(
PipelineLayoutBase** result,
const nxt::PipelineLayoutDescriptor* descriptor) {
NXT_TRY(ValidatePipelineLayoutDescriptor(this, descriptor));
NXT_TRY_ASSIGN(*result, CreatePipelineLayoutImpl(descriptor));
return {};
}
MaybeError DeviceBase::CreateQueueInternal(QueueBase** result) {
NXT_TRY_ASSIGN(*result, CreateQueueImpl());
return {};
}
MaybeError DeviceBase::CreateSamplerInternal(SamplerBase** result,
const nxt::SamplerDescriptor* descriptor) {
NXT_TRY(ValidateSamplerDescriptor(this, descriptor));
NXT_TRY_ASSIGN(*result, CreateSamplerImpl(descriptor));
return {};
}
// Other implementation details
void DeviceBase::ConsumeError(ErrorData* error) {
ASSERT(error != nullptr);
HandleError(error->GetMessage().c_str());
delete error;
}
} // namespace backend } // namespace backend

View File

@ -32,6 +32,14 @@ namespace backend {
void HandleError(const char* message); void HandleError(const char* message);
bool ConsumedError(MaybeError maybeError) {
if (NXT_UNLIKELY(maybeError.IsError())) {
ConsumeError(maybeError.AcquireError());
return true;
}
return false;
}
// Used by autogenerated code, returns itself // Used by autogenerated code, returns itself
DeviceBase* GetDevice(); DeviceBase* GetDevice();
@ -105,6 +113,16 @@ namespace backend {
virtual ResultOrError<SamplerBase*> CreateSamplerImpl( virtual ResultOrError<SamplerBase*> CreateSamplerImpl(
const nxt::SamplerDescriptor* descriptor) = 0; const nxt::SamplerDescriptor* descriptor) = 0;
MaybeError CreateBindGroupLayoutInternal(BindGroupLayoutBase** result,
const nxt::BindGroupLayoutDescriptor* descriptor);
MaybeError CreatePipelineLayoutInternal(PipelineLayoutBase** result,
const nxt::PipelineLayoutDescriptor* descriptor);
MaybeError CreateQueueInternal(QueueBase** result);
MaybeError CreateSamplerInternal(SamplerBase** result,
const nxt::SamplerDescriptor* descriptor);
void ConsumeError(ErrorData* error);
// The object caches aren't exposed in the header as they would require a lot of // The object caches aren't exposed in the header as they would require a lot of
// additional includes. // additional includes.
struct Caches; struct Caches;