Make autogenerated validation produce device or builder errors
This commit is contained in:
parent
f79df0c62d
commit
36cf2dd54b
|
@ -17,8 +17,6 @@
|
||||||
|
|
||||||
#include "{{namespace}}/GeneratedCodeIncludes.h"
|
#include "{{namespace}}/GeneratedCodeIncludes.h"
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
namespace backend {
|
namespace backend {
|
||||||
namespace {{namespace}} {
|
namespace {{namespace}} {
|
||||||
|
|
||||||
|
@ -91,18 +89,30 @@ namespace {{namespace}} {
|
||||||
{%- endfor -%}
|
{%- endfor -%}
|
||||||
) {
|
) {
|
||||||
{% if type.is_builder and method.name.canonical_case() not in ("release", "reference") %}
|
{% if type.is_builder and method.name.canonical_case() not in ("release", "reference") %}
|
||||||
if (!self->CanBeUsed()) return false;
|
if (!self->CanBeUsed()) {
|
||||||
|
self->GetDevice()->HandleError("Builder cannot be used after GetResult");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
{% else %}
|
{% else %}
|
||||||
(void) self;
|
(void) self;
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
bool error = false;
|
||||||
{% for arg in method.arguments %}
|
{% for arg in method.arguments %}
|
||||||
{% if arg.type.category == "enum" %}
|
{% if arg.type.category == "enum" %}
|
||||||
if (!CheckEnum{{as_cType(arg.type.name)}}({{as_varName(arg.name)}})) return false;
|
if (!CheckEnum{{as_cType(arg.type.name)}}({{as_varName(arg.name)}})) error = true;;
|
||||||
{% elif arg.type.category == "bitmask" %}
|
{% elif arg.type.category == "bitmask" %}
|
||||||
if (!CheckBitmask{{as_cType(arg.type.name)}}({{as_varName(arg.name)}})) return false;
|
if (!CheckBitmask{{as_cType(arg.type.name)}}({{as_varName(arg.name)}})) error = true;
|
||||||
{% else %}
|
{% else %}
|
||||||
(void) {{as_varName(arg.name)}};
|
(void) {{as_varName(arg.name)}};
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
if (error) {
|
||||||
|
{% if type.is_builder %}
|
||||||
|
self->HandleError("Bad value in {{suffix}}");
|
||||||
|
{% else %}
|
||||||
|
self->GetDevice()->HandleError("Bad value in {{suffix}}");
|
||||||
|
{% endif %}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -133,25 +143,16 @@ namespace {{namespace}} {
|
||||||
}
|
}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
//* If there is an error we forward it appropriately.
|
//* HACK(cwallez@chromium.org): special casing GetResult so that the error callback
|
||||||
if (!valid) {
|
//* is called if needed. Without this, no call to HandleResult would happen, and the
|
||||||
//* An error in a builder methods is always handled by the builder
|
//* error callback would always get called with an Unknown status
|
||||||
{% if type.is_builder %}
|
{% if type.is_builder and method.name.canonical_case() == "get result" %}
|
||||||
//* HACK(cwallez@chromium.org): special casing GetResult so that the error callback
|
if (!valid) {
|
||||||
//* is called if needed. Without this, no call to HandleResult would happen, and the
|
{{as_backendType(method.return_type)}} fakeResult = nullptr;
|
||||||
//* error callback would always get called with an Unknown status
|
bool shouldBeFalse = self->HandleResult(fakeResult);
|
||||||
{% if method.name.canonical_case() == "get result" %}
|
assert(shouldBeFalse == false);
|
||||||
{{as_backendType(method.return_type)}} fakeResult = nullptr;
|
}
|
||||||
bool shouldBeFalse = self->HandleResult(fakeResult);
|
{% endif %}
|
||||||
assert(shouldBeFalse == false);
|
|
||||||
{% else %}
|
|
||||||
self->HandleError("Error in {{suffix}}");
|
|
||||||
{% endif %}
|
|
||||||
{% else %}
|
|
||||||
// TODO get the device or builder and give it the error?
|
|
||||||
std::cout << "Error in {{suffix}}" << std::endl;
|
|
||||||
{% endif %}
|
|
||||||
}
|
|
||||||
|
|
||||||
{% if method.return_type.name.canonical_case() == "void" %}
|
{% if method.return_type.name.canonical_case() == "void" %}
|
||||||
if (!valid) return;
|
if (!valid) return;
|
||||||
|
|
|
@ -34,6 +34,10 @@ namespace backend {
|
||||||
return new BufferViewBuilder(device, this);
|
return new BufferViewBuilder(device, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DeviceBase* BufferBase::GetDevice() {
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t BufferBase::GetSize() const {
|
uint32_t BufferBase::GetSize() const {
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,8 @@ namespace backend {
|
||||||
bool HasFrozenUsage(nxt::BufferUsageBit usage) const;
|
bool HasFrozenUsage(nxt::BufferUsageBit usage) const;
|
||||||
void TransitionUsageImpl(nxt::BufferUsageBit usage);
|
void TransitionUsageImpl(nxt::BufferUsageBit usage);
|
||||||
|
|
||||||
|
DeviceBase* GetDevice();
|
||||||
|
|
||||||
// NXT API
|
// NXT API
|
||||||
BufferViewBuilder* CreateBufferViewBuilder();
|
BufferViewBuilder* CreateBufferViewBuilder();
|
||||||
void SetSubData(uint32_t start, uint32_t count, const uint32_t* data);
|
void SetSubData(uint32_t start, uint32_t count, const uint32_t* data);
|
||||||
|
|
|
@ -22,6 +22,10 @@ namespace backend {
|
||||||
return !consumed && !gotStatus;
|
return !consumed && !gotStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DeviceBase* BuilderBase::GetDevice() {
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
void BuilderBase::HandleError(const char* message) {
|
void BuilderBase::HandleError(const char* message) {
|
||||||
SetStatus(nxt::BuilderErrorStatus::Error, message);
|
SetStatus(nxt::BuilderErrorStatus::Error, message);
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,7 @@ namespace backend {
|
||||||
// Used by the auto-generated validation to prevent usage of the builder
|
// Used by the auto-generated validation to prevent usage of the builder
|
||||||
// after GetResult or an error.
|
// after GetResult or an error.
|
||||||
bool CanBeUsed() const;
|
bool CanBeUsed() const;
|
||||||
|
DeviceBase* GetDevice();
|
||||||
|
|
||||||
// Set the status of the builder to an error.
|
// Set the status of the builder to an error.
|
||||||
void HandleError(const char* message);
|
void HandleError(const char* message);
|
||||||
|
|
|
@ -61,6 +61,10 @@ namespace backend {
|
||||||
this->errorUserdata = userdata;
|
this->errorUserdata = userdata;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DeviceBase* DeviceBase::GetDevice() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
BindGroupLayoutBase* DeviceBase::GetOrCreateBindGroupLayout(const BindGroupLayoutBase* blueprint, BindGroupLayoutBuilder* builder) {
|
BindGroupLayoutBase* DeviceBase::GetOrCreateBindGroupLayout(const BindGroupLayoutBase* blueprint, BindGroupLayoutBuilder* builder) {
|
||||||
// The blueprint is only used to search in the cache and is not modified. However cached
|
// The blueprint is only used to search in the cache and is not modified. However cached
|
||||||
// objects can be modified, and unordered_set cannot search for a const pointer in a non
|
// objects can be modified, and unordered_set cannot search for a const pointer in a non
|
||||||
|
|
|
@ -32,6 +32,9 @@ namespace backend {
|
||||||
void HandleError(const char* message);
|
void HandleError(const char* message);
|
||||||
void SetErrorCallback(nxt::DeviceErrorCallback callback, nxt::CallbackUserdata userdata);
|
void SetErrorCallback(nxt::DeviceErrorCallback callback, nxt::CallbackUserdata userdata);
|
||||||
|
|
||||||
|
// Used by autogenerated code, returns itself
|
||||||
|
DeviceBase* GetDevice();
|
||||||
|
|
||||||
virtual BindGroupBase* CreateBindGroup(BindGroupBuilder* builder) = 0;
|
virtual BindGroupBase* CreateBindGroup(BindGroupBuilder* builder) = 0;
|
||||||
virtual BindGroupLayoutBase* CreateBindGroupLayout(BindGroupLayoutBuilder* builder) = 0;
|
virtual BindGroupLayoutBase* CreateBindGroupLayout(BindGroupLayoutBuilder* builder) = 0;
|
||||||
virtual BufferBase* CreateBuffer(BufferBuilder* builder) = 0;
|
virtual BufferBase* CreateBuffer(BufferBuilder* builder) = 0;
|
||||||
|
|
|
@ -21,6 +21,13 @@ namespace backend {
|
||||||
|
|
||||||
// QueueBase
|
// QueueBase
|
||||||
|
|
||||||
|
QueueBase::QueueBase(QueueBuilder* builder) : device(builder->device) {
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceBase* QueueBase::GetDevice() {
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
bool QueueBase::ValidateSubmitCommand(CommandBufferBase* command) {
|
bool QueueBase::ValidateSubmitCommand(CommandBufferBase* command) {
|
||||||
return command->ValidateResourceUsagesImmediate();
|
return command->ValidateResourceUsagesImmediate();
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,10 +24,11 @@
|
||||||
namespace backend {
|
namespace backend {
|
||||||
|
|
||||||
class QueueBase : public RefCounted {
|
class QueueBase : public RefCounted {
|
||||||
private:
|
|
||||||
bool ValidateSubmitCommand(CommandBufferBase* command);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
QueueBase(QueueBuilder* builder);
|
||||||
|
|
||||||
|
DeviceBase* GetDevice();
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool ValidateSubmit(uint32_t numCommands, T* const * commands) {
|
bool ValidateSubmit(uint32_t numCommands, T* const * commands) {
|
||||||
static_assert(std::is_base_of<CommandBufferBase, T>::value, "invalid command buffer type");
|
static_assert(std::is_base_of<CommandBufferBase, T>::value, "invalid command buffer type");
|
||||||
|
@ -39,6 +40,11 @@ namespace backend {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool ValidateSubmitCommand(CommandBufferBase* command);
|
||||||
|
|
||||||
|
DeviceBase* device;
|
||||||
};
|
};
|
||||||
|
|
||||||
class QueueBuilder : public Builder<QueueBase> {
|
class QueueBuilder : public Builder<QueueBase> {
|
||||||
|
@ -46,6 +52,7 @@ namespace backend {
|
||||||
QueueBuilder(DeviceBase* device);
|
QueueBuilder(DeviceBase* device);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
friend class QueueBase;
|
||||||
QueueBase* GetResultImpl() override;
|
QueueBase* GetResultImpl() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,10 @@ namespace backend {
|
||||||
allowedUsage(builder->allowedUsage), currentUsage(builder->currentUsage) {
|
allowedUsage(builder->allowedUsage), currentUsage(builder->currentUsage) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DeviceBase* TextureBase::GetDevice() {
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
nxt::TextureDimension TextureBase::GetDimension() const {
|
nxt::TextureDimension TextureBase::GetDimension() const {
|
||||||
return dimension;
|
return dimension;
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,8 @@ namespace backend {
|
||||||
bool IsTransitionPossible(nxt::TextureUsageBit usage) const;
|
bool IsTransitionPossible(nxt::TextureUsageBit usage) const;
|
||||||
void TransitionUsageImpl(nxt::TextureUsageBit usage);
|
void TransitionUsageImpl(nxt::TextureUsageBit usage);
|
||||||
|
|
||||||
|
DeviceBase* GetDevice();
|
||||||
|
|
||||||
// NXT API
|
// NXT API
|
||||||
TextureViewBuilder* CreateTextureViewBuilder();
|
TextureViewBuilder* CreateTextureViewBuilder();
|
||||||
void TransitionUsage(nxt::TextureUsageBit usage);
|
void TransitionUsage(nxt::TextureUsageBit usage);
|
||||||
|
|
|
@ -803,7 +803,7 @@ namespace metal {
|
||||||
// Queue
|
// Queue
|
||||||
|
|
||||||
Queue::Queue(Device* device, QueueBuilder* builder)
|
Queue::Queue(Device* device, QueueBuilder* builder)
|
||||||
: device(device) {
|
: QueueBase(builder), device(device) {
|
||||||
commandQueue = [device->GetMTLDevice() newCommandQueue];
|
commandQueue = [device->GetMTLDevice() newCommandQueue];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -167,7 +167,8 @@ namespace opengl {
|
||||||
|
|
||||||
// Queue
|
// Queue
|
||||||
|
|
||||||
Queue::Queue(Device* device, QueueBuilder* builder) : device(device) {
|
Queue::Queue(Device* device, QueueBuilder* builder)
|
||||||
|
: QueueBase(builder), device(device) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Queue::Submit(uint32_t numCommands, CommandBuffer* const * commands) {
|
void Queue::Submit(uint32_t numCommands, CommandBuffer* const * commands) {
|
||||||
|
|
Loading…
Reference in New Issue