Introduce a base class for Builder objects.
All builder objects will depend from this "Builder" base class. This will allow having the builder callback logic in only one place.
This commit is contained in:
parent
4b410a33ca
commit
5dc7915d38
|
@ -23,6 +23,8 @@ list(APPEND BACKEND_SOURCES
|
||||||
${COMMON_DIR}/BindGroupLayout.cpp
|
${COMMON_DIR}/BindGroupLayout.cpp
|
||||||
${COMMON_DIR}/BindGroupLayout.h
|
${COMMON_DIR}/BindGroupLayout.h
|
||||||
${COMMON_DIR}/BitSetIterator.h
|
${COMMON_DIR}/BitSetIterator.h
|
||||||
|
${COMMON_DIR}/Builder.cpp
|
||||||
|
${COMMON_DIR}/Builder.h
|
||||||
${COMMON_DIR}/Buffer.cpp
|
${COMMON_DIR}/Buffer.cpp
|
||||||
${COMMON_DIR}/Buffer.h
|
${COMMON_DIR}/Buffer.h
|
||||||
${COMMON_DIR}/CommandAllocator.cpp
|
${COMMON_DIR}/CommandAllocator.cpp
|
||||||
|
|
|
@ -65,32 +65,28 @@ namespace backend {
|
||||||
};
|
};
|
||||||
|
|
||||||
BindGroupBuilder::BindGroupBuilder(DeviceBase* device)
|
BindGroupBuilder::BindGroupBuilder(DeviceBase* device)
|
||||||
: device(device) {
|
: Builder(device) {
|
||||||
}
|
|
||||||
|
|
||||||
bool BindGroupBuilder::WasConsumed() const {
|
|
||||||
return consumed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BindGroupBase* BindGroupBuilder::GetResult() {
|
BindGroupBase* BindGroupBuilder::GetResult() {
|
||||||
constexpr int allProperties = BINDGROUP_PROPERTY_USAGE | BINDGROUP_PROPERTY_LAYOUT;
|
constexpr int allProperties = BINDGROUP_PROPERTY_USAGE | BINDGROUP_PROPERTY_LAYOUT;
|
||||||
if ((propertiesSet & allProperties) != allProperties) {
|
if ((propertiesSet & allProperties) != allProperties) {
|
||||||
device->HandleError("Bindgroup missing properties");
|
HandleError("Bindgroup missing properties");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setMask != layout->GetBindingInfo().mask) {
|
if (setMask != layout->GetBindingInfo().mask) {
|
||||||
device->HandleError("Bindgroup missing bindings");
|
HandleError("Bindgroup missing bindings");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
consumed = true;
|
MarkConsumed();
|
||||||
return device->CreateBindGroup(this);
|
return device->CreateBindGroup(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BindGroupBuilder::SetLayout(BindGroupLayoutBase* layout) {
|
void BindGroupBuilder::SetLayout(BindGroupLayoutBase* layout) {
|
||||||
if ((propertiesSet & BINDGROUP_PROPERTY_LAYOUT) != 0) {
|
if ((propertiesSet & BINDGROUP_PROPERTY_LAYOUT) != 0) {
|
||||||
device->HandleError("Bindgroup layout property set multiple times");
|
HandleError("Bindgroup layout property set multiple times");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,7 +96,7 @@ namespace backend {
|
||||||
|
|
||||||
void BindGroupBuilder::SetUsage(nxt::BindGroupUsage usage) {
|
void BindGroupBuilder::SetUsage(nxt::BindGroupUsage usage) {
|
||||||
if ((propertiesSet & BINDGROUP_PROPERTY_USAGE) != 0) {
|
if ((propertiesSet & BINDGROUP_PROPERTY_USAGE) != 0) {
|
||||||
device->HandleError("Bindgroup usage property set multiple times");
|
HandleError("Bindgroup usage property set multiple times");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,12 +123,12 @@ namespace backend {
|
||||||
|
|
||||||
case nxt::BindingType::Sampler:
|
case nxt::BindingType::Sampler:
|
||||||
case nxt::BindingType::SampledTexture:
|
case nxt::BindingType::SampledTexture:
|
||||||
device->HandleError("Setting buffer for a wrong binding type");
|
HandleError("Setting buffer for a wrong binding type");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(bufferViews[j]->GetBuffer()->GetAllowedUsage() & requiredBit)) {
|
if (!(bufferViews[j]->GetBuffer()->GetAllowedUsage() & requiredBit)) {
|
||||||
device->HandleError("Buffer needs to allow the correct usage bit");
|
HandleError("Buffer needs to allow the correct usage bit");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -148,7 +144,7 @@ namespace backend {
|
||||||
const auto& layoutInfo = layout->GetBindingInfo();
|
const auto& layoutInfo = layout->GetBindingInfo();
|
||||||
for (size_t i = start, j = 0; i < start + count; ++i, ++j) {
|
for (size_t i = start, j = 0; i < start + count; ++i, ++j) {
|
||||||
if (layoutInfo.types[i] != nxt::BindingType::Sampler) {
|
if (layoutInfo.types[i] != nxt::BindingType::Sampler) {
|
||||||
device->HandleError("Setting binding for a wrong layout binding type");
|
HandleError("Setting binding for a wrong layout binding type");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -164,12 +160,12 @@ namespace backend {
|
||||||
const auto& layoutInfo = layout->GetBindingInfo();
|
const auto& layoutInfo = layout->GetBindingInfo();
|
||||||
for (size_t i = start, j = 0; i < start + count; ++i, ++j) {
|
for (size_t i = start, j = 0; i < start + count; ++i, ++j) {
|
||||||
if (layoutInfo.types[i] != nxt::BindingType::SampledTexture) {
|
if (layoutInfo.types[i] != nxt::BindingType::SampledTexture) {
|
||||||
device->HandleError("Setting binding for a wrong layout binding type");
|
HandleError("Setting binding for a wrong layout binding type");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(textureViews[j]->GetTexture()->GetAllowedUsage() & nxt::TextureUsageBit::Sampled)) {
|
if (!(textureViews[j]->GetTexture()->GetAllowedUsage() & nxt::TextureUsageBit::Sampled)) {
|
||||||
device->HandleError("Texture needs to allow the sampled usage bit");
|
HandleError("Texture needs to allow the sampled usage bit");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -186,24 +182,24 @@ namespace backend {
|
||||||
|
|
||||||
bool BindGroupBuilder::SetBindingsValidationBase(uint32_t start, uint32_t count) {
|
bool BindGroupBuilder::SetBindingsValidationBase(uint32_t start, uint32_t count) {
|
||||||
if (start + count > kMaxBindingsPerGroup) {
|
if (start + count > kMaxBindingsPerGroup) {
|
||||||
device->HandleError("Setting bindings type over maximum number of bindings");
|
HandleError("Setting bindings type over maximum number of bindings");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((propertiesSet & BINDGROUP_PROPERTY_LAYOUT) == 0) {
|
if ((propertiesSet & BINDGROUP_PROPERTY_LAYOUT) == 0) {
|
||||||
device->HandleError("Bindgroup layout must be set before views");
|
HandleError("Bindgroup layout must be set before views");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& layoutInfo = layout->GetBindingInfo();
|
const auto& layoutInfo = layout->GetBindingInfo();
|
||||||
for (size_t i = start, j = 0; i < start + count; ++i, ++j) {
|
for (size_t i = start, j = 0; i < start + count; ++i, ++j) {
|
||||||
if (setMask[i]) {
|
if (setMask[i]) {
|
||||||
device->HandleError("Setting already set binding");
|
HandleError("Setting already set binding");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!layoutInfo.mask[i]) {
|
if (!layoutInfo.mask[i]) {
|
||||||
device->HandleError("Setting binding that isn't present in the layout");
|
HandleError("Setting binding that isn't present in the layout");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#define BACKEND_COMMON_BINDGROUP_H_
|
#define BACKEND_COMMON_BINDGROUP_H_
|
||||||
|
|
||||||
#include "Forward.h"
|
#include "Forward.h"
|
||||||
|
#include "Builder.h"
|
||||||
#include "RefCounted.h"
|
#include "RefCounted.h"
|
||||||
|
|
||||||
#include "nxt/nxtcpp.h"
|
#include "nxt/nxtcpp.h"
|
||||||
|
@ -42,12 +43,10 @@ namespace backend {
|
||||||
std::array<Ref<RefCounted>, kMaxBindingsPerGroup> bindings;
|
std::array<Ref<RefCounted>, kMaxBindingsPerGroup> bindings;
|
||||||
};
|
};
|
||||||
|
|
||||||
class BindGroupBuilder : public RefCounted {
|
class BindGroupBuilder : public Builder {
|
||||||
public:
|
public:
|
||||||
BindGroupBuilder(DeviceBase* device);
|
BindGroupBuilder(DeviceBase* device);
|
||||||
|
|
||||||
bool WasConsumed() const;
|
|
||||||
|
|
||||||
// NXT API
|
// NXT API
|
||||||
BindGroupBase* GetResult();
|
BindGroupBase* GetResult();
|
||||||
void SetLayout(BindGroupLayoutBase* layout);
|
void SetLayout(BindGroupLayoutBase* layout);
|
||||||
|
@ -80,10 +79,8 @@ namespace backend {
|
||||||
void SetBindingsBase(uint32_t start, uint32_t count, RefCounted* const * objects);
|
void SetBindingsBase(uint32_t start, uint32_t count, RefCounted* const * objects);
|
||||||
bool SetBindingsValidationBase(uint32_t start, uint32_t count);
|
bool SetBindingsValidationBase(uint32_t start, uint32_t count);
|
||||||
|
|
||||||
DeviceBase* device;
|
|
||||||
std::bitset<kMaxBindingsPerGroup> setMask;
|
std::bitset<kMaxBindingsPerGroup> setMask;
|
||||||
int propertiesSet = 0;
|
int propertiesSet = 0;
|
||||||
bool consumed = false;
|
|
||||||
|
|
||||||
Ref<BindGroupLayoutBase> layout;
|
Ref<BindGroupLayoutBase> layout;
|
||||||
nxt::BindGroupUsage usage;
|
nxt::BindGroupUsage usage;
|
||||||
|
|
|
@ -94,11 +94,7 @@ namespace backend {
|
||||||
|
|
||||||
// BindGroupLayoutBuilder
|
// BindGroupLayoutBuilder
|
||||||
|
|
||||||
BindGroupLayoutBuilder::BindGroupLayoutBuilder(DeviceBase* device) : device(device) {
|
BindGroupLayoutBuilder::BindGroupLayoutBuilder(DeviceBase* device) : Builder(device) {
|
||||||
}
|
|
||||||
|
|
||||||
bool BindGroupLayoutBuilder::WasConsumed() const {
|
|
||||||
return consumed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const BindGroupLayoutBase::LayoutBindingInfo& BindGroupLayoutBuilder::GetBindingInfo() const {
|
const BindGroupLayoutBase::LayoutBindingInfo& BindGroupLayoutBuilder::GetBindingInfo() const {
|
||||||
|
@ -106,7 +102,7 @@ namespace backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
BindGroupLayoutBase* BindGroupLayoutBuilder::GetResult() {
|
BindGroupLayoutBase* BindGroupLayoutBuilder::GetResult() {
|
||||||
consumed = true;
|
MarkConsumed();
|
||||||
BindGroupLayoutBase blueprint(this, true);
|
BindGroupLayoutBase blueprint(this, true);
|
||||||
|
|
||||||
auto* result = device->GetOrCreateBindGroupLayout(&blueprint, this);
|
auto* result = device->GetOrCreateBindGroupLayout(&blueprint, this);
|
||||||
|
@ -116,13 +112,13 @@ namespace backend {
|
||||||
|
|
||||||
void BindGroupLayoutBuilder::SetBindingsType(nxt::ShaderStageBit visibility, nxt::BindingType bindingType, uint32_t start, uint32_t count) {
|
void BindGroupLayoutBuilder::SetBindingsType(nxt::ShaderStageBit visibility, nxt::BindingType bindingType, uint32_t start, uint32_t count) {
|
||||||
if (start + count > kMaxBindingsPerGroup) {
|
if (start + count > kMaxBindingsPerGroup) {
|
||||||
device->HandleError("Setting bindings type over maximum number of bindings");
|
HandleError("Setting bindings type over maximum number of bindings");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = start; i < start + count; i++) {
|
for (size_t i = start; i < start + count; i++) {
|
||||||
if (bindingInfo.mask[i]) {
|
if (bindingInfo.mask[i]) {
|
||||||
device->HandleError("Setting already set binding type");
|
HandleError("Setting already set binding type");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bindingInfo.mask.set(i);
|
bindingInfo.mask.set(i);
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#define BACKEND_COMMON_BINDGROUPLAYOUT_H_
|
#define BACKEND_COMMON_BINDGROUPLAYOUT_H_
|
||||||
|
|
||||||
#include "Forward.h"
|
#include "Forward.h"
|
||||||
|
#include "Builder.h"
|
||||||
#include "RefCounted.h"
|
#include "RefCounted.h"
|
||||||
|
|
||||||
#include "nxt/nxtcpp.h"
|
#include "nxt/nxtcpp.h"
|
||||||
|
@ -43,11 +44,10 @@ namespace backend {
|
||||||
bool blueprint = false;
|
bool blueprint = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class BindGroupLayoutBuilder : public RefCounted {
|
class BindGroupLayoutBuilder : public Builder {
|
||||||
public:
|
public:
|
||||||
BindGroupLayoutBuilder(DeviceBase* device);
|
BindGroupLayoutBuilder(DeviceBase* device);
|
||||||
|
|
||||||
bool WasConsumed() const;
|
|
||||||
const BindGroupLayoutBase::LayoutBindingInfo& GetBindingInfo() const;
|
const BindGroupLayoutBase::LayoutBindingInfo& GetBindingInfo() const;
|
||||||
|
|
||||||
// NXT API
|
// NXT API
|
||||||
|
@ -57,9 +57,7 @@ namespace backend {
|
||||||
private:
|
private:
|
||||||
friend class BindGroupLayoutBase;
|
friend class BindGroupLayoutBase;
|
||||||
|
|
||||||
DeviceBase* device;
|
|
||||||
BindGroupLayoutBase::LayoutBindingInfo bindingInfo;
|
BindGroupLayoutBase::LayoutBindingInfo bindingInfo;
|
||||||
bool consumed = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Implements the functors necessary for the unordered_set<BGL*>-based cache.
|
// Implements the functors necessary for the unordered_set<BGL*>-based cache.
|
||||||
|
|
|
@ -118,32 +118,28 @@ namespace backend {
|
||||||
BUFFER_PROPERTY_SIZE = 0x4,
|
BUFFER_PROPERTY_SIZE = 0x4,
|
||||||
};
|
};
|
||||||
|
|
||||||
BufferBuilder::BufferBuilder(DeviceBase* device) : device(device) {
|
BufferBuilder::BufferBuilder(DeviceBase* device) : Builder(device) {
|
||||||
}
|
|
||||||
|
|
||||||
bool BufferBuilder::WasConsumed() const {
|
|
||||||
return consumed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferBase* BufferBuilder::GetResult() {
|
BufferBase* BufferBuilder::GetResult() {
|
||||||
constexpr int allProperties = BUFFER_PROPERTY_ALLOWED_USAGE | BUFFER_PROPERTY_SIZE;
|
constexpr int allProperties = BUFFER_PROPERTY_ALLOWED_USAGE | BUFFER_PROPERTY_SIZE;
|
||||||
if ((propertiesSet & allProperties) != allProperties) {
|
if ((propertiesSet & allProperties) != allProperties) {
|
||||||
device->HandleError("Buffer missing properties");
|
HandleError("Buffer missing properties");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!BufferBase::IsUsagePossible(allowedUsage, currentUsage)) {
|
if (!BufferBase::IsUsagePossible(allowedUsage, currentUsage)) {
|
||||||
device->HandleError("Initial buffer usage is not allowed");
|
HandleError("Initial buffer usage is not allowed");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
consumed = true;
|
MarkConsumed();
|
||||||
return device->CreateBuffer(this);
|
return device->CreateBuffer(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BufferBuilder::SetAllowedUsage(nxt::BufferUsageBit usage) {
|
void BufferBuilder::SetAllowedUsage(nxt::BufferUsageBit usage) {
|
||||||
if ((propertiesSet & BUFFER_PROPERTY_ALLOWED_USAGE) != 0) {
|
if ((propertiesSet & BUFFER_PROPERTY_ALLOWED_USAGE) != 0) {
|
||||||
device->HandleError("Buffer allowedUsage property set multiple times");
|
HandleError("Buffer allowedUsage property set multiple times");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,7 +149,7 @@ namespace backend {
|
||||||
|
|
||||||
void BufferBuilder::SetInitialUsage(nxt::BufferUsageBit usage) {
|
void BufferBuilder::SetInitialUsage(nxt::BufferUsageBit usage) {
|
||||||
if ((propertiesSet & BUFFER_PROPERTY_INITIAL_USAGE) != 0) {
|
if ((propertiesSet & BUFFER_PROPERTY_INITIAL_USAGE) != 0) {
|
||||||
device->HandleError("Buffer initialUsage property set multiple times");
|
HandleError("Buffer initialUsage property set multiple times");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,7 +159,7 @@ namespace backend {
|
||||||
|
|
||||||
void BufferBuilder::SetSize(uint32_t size) {
|
void BufferBuilder::SetSize(uint32_t size) {
|
||||||
if ((propertiesSet & BUFFER_PROPERTY_SIZE) != 0) {
|
if ((propertiesSet & BUFFER_PROPERTY_SIZE) != 0) {
|
||||||
device->HandleError("Buffer size property set multiple times");
|
HandleError("Buffer size property set multiple times");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,32 +192,29 @@ namespace backend {
|
||||||
};
|
};
|
||||||
|
|
||||||
BufferViewBuilder::BufferViewBuilder(DeviceBase* device, BufferBase* buffer)
|
BufferViewBuilder::BufferViewBuilder(DeviceBase* device, BufferBase* buffer)
|
||||||
: device(device), buffer(buffer) {
|
: Builder(device), buffer(buffer) {
|
||||||
}
|
|
||||||
|
|
||||||
bool BufferViewBuilder::WasConsumed() const {
|
|
||||||
return consumed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferViewBase* BufferViewBuilder::GetResult() {
|
BufferViewBase* BufferViewBuilder::GetResult() {
|
||||||
constexpr int allProperties = BUFFER_VIEW_PROPERTY_EXTENT;
|
constexpr int allProperties = BUFFER_VIEW_PROPERTY_EXTENT;
|
||||||
if ((propertiesSet & allProperties) != allProperties) {
|
if ((propertiesSet & allProperties) != allProperties) {
|
||||||
device->HandleError("Buffer view missing properties");
|
HandleError("Buffer view missing properties");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MarkConsumed();
|
||||||
return device->CreateBufferView(this);
|
return device->CreateBufferView(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BufferViewBuilder::SetExtent(uint32_t offset, uint32_t size) {
|
void BufferViewBuilder::SetExtent(uint32_t offset, uint32_t size) {
|
||||||
if ((propertiesSet & BUFFER_VIEW_PROPERTY_EXTENT) != 0) {
|
if ((propertiesSet & BUFFER_VIEW_PROPERTY_EXTENT) != 0) {
|
||||||
device->HandleError("Buffer view extent property set multiple times");
|
HandleError("Buffer view extent property set multiple times");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t viewEnd = static_cast<uint64_t>(offset) + static_cast<uint64_t>(size);
|
uint64_t viewEnd = static_cast<uint64_t>(offset) + static_cast<uint64_t>(size);
|
||||||
if (viewEnd > static_cast<uint64_t>(buffer->GetSize())) {
|
if (viewEnd > static_cast<uint64_t>(buffer->GetSize())) {
|
||||||
device->HandleError("Buffer view end is OOB");
|
HandleError("Buffer view end is OOB");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#define BACKEND_COMMON_BUFFER_H_
|
#define BACKEND_COMMON_BUFFER_H_
|
||||||
|
|
||||||
#include "Forward.h"
|
#include "Forward.h"
|
||||||
|
#include "Builder.h"
|
||||||
#include "RefCounted.h"
|
#include "RefCounted.h"
|
||||||
|
|
||||||
#include "nxt/nxtcpp.h"
|
#include "nxt/nxtcpp.h"
|
||||||
|
@ -51,12 +52,10 @@ namespace backend {
|
||||||
bool frozen = false;
|
bool frozen = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class BufferBuilder : public RefCounted {
|
class BufferBuilder : public Builder {
|
||||||
public:
|
public:
|
||||||
BufferBuilder(DeviceBase* device);
|
BufferBuilder(DeviceBase* device);
|
||||||
|
|
||||||
bool WasConsumed() const;
|
|
||||||
|
|
||||||
// NXT API
|
// NXT API
|
||||||
BufferBase* GetResult();
|
BufferBase* GetResult();
|
||||||
void SetAllowedUsage(nxt::BufferUsageBit usage);
|
void SetAllowedUsage(nxt::BufferUsageBit usage);
|
||||||
|
@ -66,12 +65,10 @@ namespace backend {
|
||||||
private:
|
private:
|
||||||
friend class BufferBase;
|
friend class BufferBase;
|
||||||
|
|
||||||
DeviceBase* device;
|
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
nxt::BufferUsageBit allowedUsage = nxt::BufferUsageBit::None;
|
nxt::BufferUsageBit allowedUsage = nxt::BufferUsageBit::None;
|
||||||
nxt::BufferUsageBit currentUsage = nxt::BufferUsageBit::None;
|
nxt::BufferUsageBit currentUsage = nxt::BufferUsageBit::None;
|
||||||
int propertiesSet = 0;
|
int propertiesSet = 0;
|
||||||
bool consumed = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class BufferViewBase : public RefCounted {
|
class BufferViewBase : public RefCounted {
|
||||||
|
@ -88,12 +85,10 @@ namespace backend {
|
||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
class BufferViewBuilder : public RefCounted {
|
class BufferViewBuilder : public Builder {
|
||||||
public:
|
public:
|
||||||
BufferViewBuilder(DeviceBase* device, BufferBase* buffer);
|
BufferViewBuilder(DeviceBase* device, BufferBase* buffer);
|
||||||
|
|
||||||
bool WasConsumed() const;
|
|
||||||
|
|
||||||
// NXT API
|
// NXT API
|
||||||
BufferViewBase* GetResult();
|
BufferViewBase* GetResult();
|
||||||
void SetExtent(uint32_t offset, uint32_t size);
|
void SetExtent(uint32_t offset, uint32_t size);
|
||||||
|
@ -101,12 +96,10 @@ namespace backend {
|
||||||
private:
|
private:
|
||||||
friend class BufferViewBase;
|
friend class BufferViewBase;
|
||||||
|
|
||||||
DeviceBase* device;
|
|
||||||
Ref<BufferBase> buffer;
|
Ref<BufferBase> buffer;
|
||||||
uint32_t offset = 0;
|
uint32_t offset = 0;
|
||||||
uint32_t size = 0;
|
uint32_t size = 0;
|
||||||
int propertiesSet = 0;
|
int propertiesSet = 0;
|
||||||
bool consumed = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
// Copyright 2017 The NXT 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 "Builder.h"
|
||||||
|
|
||||||
|
#include "Device.h"
|
||||||
|
|
||||||
|
namespace backend {
|
||||||
|
|
||||||
|
bool Builder::WasConsumed() const {
|
||||||
|
return consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
Builder::Builder(DeviceBase* device) : device(device) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void Builder::MarkConsumed() {
|
||||||
|
ASSERT(!consumed);
|
||||||
|
consumed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Builder::HandleError(const char* message) {
|
||||||
|
device->HandleError(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
// Copyright 2017 The NXT 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 BACKEND_COMMON_BUILDER_H_
|
||||||
|
#define BACKEND_COMMON_BUILDER_H_
|
||||||
|
|
||||||
|
#include "Forward.h"
|
||||||
|
#include "RefCounted.h"
|
||||||
|
|
||||||
|
namespace backend {
|
||||||
|
|
||||||
|
class Builder : public RefCounted {
|
||||||
|
public:
|
||||||
|
bool WasConsumed() const;
|
||||||
|
void HandleError(const char* message);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Builder(DeviceBase* device);
|
||||||
|
|
||||||
|
void MarkConsumed();
|
||||||
|
|
||||||
|
DeviceBase* const device;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool consumed = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // BACKEND_COMMON_BUILDER_H_
|
|
@ -132,20 +132,16 @@ namespace backend {
|
||||||
commands->DataWasDestroyed();
|
commands->DataWasDestroyed();
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandBufferBuilder::CommandBufferBuilder(DeviceBase* device) : device(device) {
|
CommandBufferBuilder::CommandBufferBuilder(DeviceBase* device) : Builder(device) {
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandBufferBuilder::~CommandBufferBuilder() {
|
CommandBufferBuilder::~CommandBufferBuilder() {
|
||||||
if (!consumed) {
|
if (!WasConsumed()) {
|
||||||
MoveToIterator();
|
MoveToIterator();
|
||||||
FreeCommands(&iterator);
|
FreeCommands(&iterator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandBufferBuilder::WasConsumed() const {
|
|
||||||
return consumed;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum ValidationAspect {
|
enum ValidationAspect {
|
||||||
VALIDATION_ASPECT_RENDER_PIPELINE,
|
VALIDATION_ASPECT_RENDER_PIPELINE,
|
||||||
VALIDATION_ASPECT_COMPUTE_PIPELINE,
|
VALIDATION_ASPECT_COMPUTE_PIPELINE,
|
||||||
|
@ -215,7 +211,7 @@ namespace backend {
|
||||||
|
|
||||||
auto buffer = group->GetBindingAsBufferView(i)->GetBuffer();
|
auto buffer = group->GetBindingAsBufferView(i)->GetBuffer();
|
||||||
if (!bufferHasGuaranteedUsageBit(buffer, requiredUsage)) {
|
if (!bufferHasGuaranteedUsageBit(buffer, requiredUsage)) {
|
||||||
device->HandleError("Can't guarantee buffer usage needed by bind group");
|
HandleError("Can't guarantee buffer usage needed by bind group");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -226,7 +222,7 @@ namespace backend {
|
||||||
|
|
||||||
auto texture = group->GetBindingAsTextureView(i)->GetTexture();
|
auto texture = group->GetBindingAsTextureView(i)->GetTexture();
|
||||||
if (!textureHasGuaranteedUsageBit(texture, requiredUsage)) {
|
if (!textureHasGuaranteedUsageBit(texture, requiredUsage)) {
|
||||||
device->HandleError("Can't guarantee texture usage needed by bind group");
|
HandleError("Can't guarantee texture usage needed by bind group");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -256,17 +252,17 @@ namespace backend {
|
||||||
uint32_t level = copy->level;
|
uint32_t level = copy->level;
|
||||||
|
|
||||||
if (!bufferHasGuaranteedUsageBit(buffer, nxt::BufferUsageBit::TransferSrc)) {
|
if (!bufferHasGuaranteedUsageBit(buffer, nxt::BufferUsageBit::TransferSrc)) {
|
||||||
device->HandleError("Buffer needs the transfer source usage bit");
|
HandleError("Buffer needs the transfer source usage bit");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!textureHasGuaranteedUsageBit(texture, nxt::TextureUsageBit::TransferDst)) {
|
if (!textureHasGuaranteedUsageBit(texture, nxt::TextureUsageBit::TransferDst)) {
|
||||||
device->HandleError("Texture needs the transfer destination usage bit");
|
HandleError("Texture needs the transfer destination usage bit");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (width == 0 || height == 0 || depth == 0) {
|
if (width == 0 || height == 0 || depth == 0) {
|
||||||
device->HandleError("Empty copy");
|
HandleError("Empty copy");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,7 +271,7 @@ namespace backend {
|
||||||
uint64_t dataSize = width * height * depth * pixelSize;
|
uint64_t dataSize = width * height * depth * pixelSize;
|
||||||
|
|
||||||
if (dataSize + static_cast<uint64_t>(bufferOffset) > static_cast<uint64_t>(buffer->GetSize())) {
|
if (dataSize + static_cast<uint64_t>(bufferOffset) > static_cast<uint64_t>(buffer->GetSize())) {
|
||||||
device->HandleError("Copy would read after end of the buffer");
|
HandleError("Copy would read after end of the buffer");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,7 +279,7 @@ namespace backend {
|
||||||
y + height > static_cast<uint64_t>(texture->GetHeight()) ||
|
y + height > static_cast<uint64_t>(texture->GetHeight()) ||
|
||||||
z + depth > static_cast<uint64_t>(texture->GetDepth()) ||
|
z + depth > static_cast<uint64_t>(texture->GetDepth()) ||
|
||||||
level > texture->GetNumMipLevels()) {
|
level > texture->GetNumMipLevels()) {
|
||||||
device->HandleError("Copy would write outside of the texture");
|
HandleError("Copy would write outside of the texture");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -311,7 +307,7 @@ namespace backend {
|
||||||
|
|
||||||
// Check again if anything is missing
|
// Check again if anything is missing
|
||||||
if ((requiredDispatchAspects & ~aspects).any()) {
|
if ((requiredDispatchAspects & ~aspects).any()) {
|
||||||
device->HandleError("Some dispatch state is missing");
|
HandleError("Some dispatch state is missing");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -339,7 +335,7 @@ namespace backend {
|
||||||
|
|
||||||
// Check again if anything is missing
|
// Check again if anything is missing
|
||||||
if ((requiredDrawAspects & ~aspects).any()) {
|
if ((requiredDrawAspects & ~aspects).any()) {
|
||||||
device->HandleError("Some draw state is missing");
|
HandleError("Some draw state is missing");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -351,7 +347,7 @@ namespace backend {
|
||||||
DrawElementsCmd* draw = iterator.NextCommand<DrawElementsCmd>();
|
DrawElementsCmd* draw = iterator.NextCommand<DrawElementsCmd>();
|
||||||
|
|
||||||
if (!aspects[VALIDATION_ASPECT_INDEX_BUFFER]) {
|
if (!aspects[VALIDATION_ASPECT_INDEX_BUFFER]) {
|
||||||
device->HandleError("Draw elements requires an index buffer");
|
HandleError("Draw elements requires an index buffer");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -394,7 +390,7 @@ namespace backend {
|
||||||
SetPushConstantsCmd* cmd = iterator.NextCommand<SetPushConstantsCmd>();
|
SetPushConstantsCmd* cmd = iterator.NextCommand<SetPushConstantsCmd>();
|
||||||
iterator.NextData<uint32_t>(cmd->count);
|
iterator.NextData<uint32_t>(cmd->count);
|
||||||
if (cmd->count + cmd->offset > kMaxPushConstants) {
|
if (cmd->count + cmd->offset > kMaxPushConstants) {
|
||||||
device->HandleError("Setting pushconstants past the limit");
|
HandleError("Setting pushconstants past the limit");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -406,7 +402,7 @@ namespace backend {
|
||||||
uint32_t index = cmd->index;
|
uint32_t index = cmd->index;
|
||||||
|
|
||||||
if (cmd->group->GetLayout() != lastPipeline->GetLayout()->GetBindGroupLayout(index)) {
|
if (cmd->group->GetLayout() != lastPipeline->GetLayout()->GetBindGroupLayout(index)) {
|
||||||
device->HandleError("Bind group layout mismatch");
|
HandleError("Bind group layout mismatch");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!validateBindGroupUsages(cmd->group.Get())) {
|
if (!validateBindGroupUsages(cmd->group.Get())) {
|
||||||
|
@ -422,7 +418,7 @@ namespace backend {
|
||||||
auto buffer = cmd->buffer;
|
auto buffer = cmd->buffer;
|
||||||
auto usage = nxt::BufferUsageBit::Index;
|
auto usage = nxt::BufferUsageBit::Index;
|
||||||
if (!bufferHasGuaranteedUsageBit(buffer.Get(), usage)) {
|
if (!bufferHasGuaranteedUsageBit(buffer.Get(), usage)) {
|
||||||
device->HandleError("Buffer needs the index usage bit to be guaranteed");
|
HandleError("Buffer needs the index usage bit to be guaranteed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -440,7 +436,7 @@ namespace backend {
|
||||||
auto buffer = buffers[i];
|
auto buffer = buffers[i];
|
||||||
auto usage = nxt::BufferUsageBit::Vertex;
|
auto usage = nxt::BufferUsageBit::Vertex;
|
||||||
if (!bufferHasGuaranteedUsageBit(buffer.Get(), usage)) {
|
if (!bufferHasGuaranteedUsageBit(buffer.Get(), usage)) {
|
||||||
device->HandleError("Buffer needs vertex usage bit to be guaranteed");
|
HandleError("Buffer needs vertex usage bit to be guaranteed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
inputsSet.set(cmd->startSlot + i);
|
inputsSet.set(cmd->startSlot + i);
|
||||||
|
@ -455,7 +451,7 @@ namespace backend {
|
||||||
auto usage = cmd->usage;
|
auto usage = cmd->usage;
|
||||||
|
|
||||||
if (!cmd->buffer->IsTransitionPossible(cmd->usage)) {
|
if (!cmd->buffer->IsTransitionPossible(cmd->usage)) {
|
||||||
device->HandleError("Buffer frozen or usage not allowed");
|
HandleError("Buffer frozen or usage not allowed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -472,7 +468,7 @@ namespace backend {
|
||||||
auto usage = cmd->usage;
|
auto usage = cmd->usage;
|
||||||
|
|
||||||
if (!cmd->texture->IsTransitionPossible(cmd->usage)) {
|
if (!cmd->texture->IsTransitionPossible(cmd->usage)) {
|
||||||
device->HandleError("Texture frozen or usage not allowed");
|
HandleError("Texture frozen or usage not allowed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -493,7 +489,7 @@ namespace backend {
|
||||||
|
|
||||||
CommandBufferBase* CommandBufferBuilder::GetResult() {
|
CommandBufferBase* CommandBufferBuilder::GetResult() {
|
||||||
MoveToIterator();
|
MoveToIterator();
|
||||||
consumed = true;
|
MarkConsumed();
|
||||||
return device->CreateCommandBuffer(this);
|
return device->CreateCommandBuffer(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -548,7 +544,7 @@ namespace backend {
|
||||||
|
|
||||||
void CommandBufferBuilder::SetPushConstants(nxt::ShaderStageBit stage, uint32_t offset, uint32_t count, const void* data) {
|
void CommandBufferBuilder::SetPushConstants(nxt::ShaderStageBit stage, uint32_t offset, uint32_t count, const void* data) {
|
||||||
if (offset + count > kMaxPushConstants) {
|
if (offset + count > kMaxPushConstants) {
|
||||||
device->HandleError("Setting too many push constants");
|
HandleError("Setting too many push constants");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -564,7 +560,7 @@ namespace backend {
|
||||||
|
|
||||||
void CommandBufferBuilder::SetBindGroup(uint32_t groupIndex, BindGroupBase* group) {
|
void CommandBufferBuilder::SetBindGroup(uint32_t groupIndex, BindGroupBase* group) {
|
||||||
if (groupIndex >= kMaxBindGroups) {
|
if (groupIndex >= kMaxBindGroups) {
|
||||||
device->HandleError("Setting bind group over the max");
|
HandleError("Setting bind group over the max");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "nxt/nxtcpp.h"
|
#include "nxt/nxtcpp.h"
|
||||||
|
|
||||||
#include "CommandAllocator.h"
|
#include "CommandAllocator.h"
|
||||||
|
#include "Builder.h"
|
||||||
#include "RefCounted.h"
|
#include "RefCounted.h"
|
||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
|
@ -44,12 +45,11 @@ namespace backend {
|
||||||
std::set<TextureBase*> texturesTransitioned;
|
std::set<TextureBase*> texturesTransitioned;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CommandBufferBuilder : public RefCounted {
|
class CommandBufferBuilder : public Builder {
|
||||||
public:
|
public:
|
||||||
CommandBufferBuilder(DeviceBase* device);
|
CommandBufferBuilder(DeviceBase* device);
|
||||||
~CommandBufferBuilder();
|
~CommandBufferBuilder();
|
||||||
|
|
||||||
bool WasConsumed() const;
|
|
||||||
bool ValidateGetResult();
|
bool ValidateGetResult();
|
||||||
|
|
||||||
CommandIterator AcquireCommands();
|
CommandIterator AcquireCommands();
|
||||||
|
@ -83,10 +83,8 @@ namespace backend {
|
||||||
|
|
||||||
void MoveToIterator();
|
void MoveToIterator();
|
||||||
|
|
||||||
DeviceBase* device;
|
|
||||||
CommandAllocator allocator;
|
CommandAllocator allocator;
|
||||||
CommandIterator iterator;
|
CommandIterator iterator;
|
||||||
bool consumed = false;
|
|
||||||
bool movedToIterator = false;
|
bool movedToIterator = false;
|
||||||
// These pointers will remain valid since they are referenced by
|
// These pointers will remain valid since they are referenced by
|
||||||
// the bind groups which are referenced by this command buffer.
|
// the bind groups which are referenced by this command buffer.
|
||||||
|
|
|
@ -78,37 +78,34 @@ namespace backend {
|
||||||
|
|
||||||
// InputStateBuilder
|
// InputStateBuilder
|
||||||
|
|
||||||
InputStateBuilder::InputStateBuilder(DeviceBase* device) : device(device) {
|
InputStateBuilder::InputStateBuilder(DeviceBase* device) : Builder(device) {
|
||||||
}
|
|
||||||
|
|
||||||
bool InputStateBuilder::WasConsumed() const {
|
|
||||||
return consumed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InputStateBase* InputStateBuilder::GetResult() {
|
InputStateBase* InputStateBuilder::GetResult() {
|
||||||
for (uint32_t location = 0; location < kMaxVertexAttributes; ++location) {
|
for (uint32_t location = 0; location < kMaxVertexAttributes; ++location) {
|
||||||
if (attributesSetMask[location] &&
|
if (attributesSetMask[location] &&
|
||||||
!inputsSetMask[attributeInfos[location].bindingSlot]) {
|
!inputsSetMask[attributeInfos[location].bindingSlot]) {
|
||||||
device->HandleError("Attribute uses unset input");
|
HandleError("Attribute uses unset input");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
consumed = true;
|
|
||||||
|
MarkConsumed();
|
||||||
return device->CreateInputState(this);
|
return device->CreateInputState(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputStateBuilder::SetAttribute(uint32_t shaderLocation,
|
void InputStateBuilder::SetAttribute(uint32_t shaderLocation,
|
||||||
uint32_t bindingSlot, nxt::VertexFormat format, uint32_t offset) {
|
uint32_t bindingSlot, nxt::VertexFormat format, uint32_t offset) {
|
||||||
if (shaderLocation >= kMaxVertexAttributes) {
|
if (shaderLocation >= kMaxVertexAttributes) {
|
||||||
device->HandleError("Setting attribute out of bounds");
|
HandleError("Setting attribute out of bounds");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (bindingSlot >= kMaxVertexInputs) {
|
if (bindingSlot >= kMaxVertexInputs) {
|
||||||
device->HandleError("Binding slot out of bounds");
|
HandleError("Binding slot out of bounds");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (attributesSetMask[shaderLocation]) {
|
if (attributesSetMask[shaderLocation]) {
|
||||||
device->HandleError("Setting already set attribute");
|
HandleError("Setting already set attribute");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,11 +119,11 @@ namespace backend {
|
||||||
void InputStateBuilder::SetInput(uint32_t bindingSlot, uint32_t stride,
|
void InputStateBuilder::SetInput(uint32_t bindingSlot, uint32_t stride,
|
||||||
nxt::InputStepMode stepMode) {
|
nxt::InputStepMode stepMode) {
|
||||||
if (bindingSlot >= kMaxVertexInputs) {
|
if (bindingSlot >= kMaxVertexInputs) {
|
||||||
device->HandleError("Setting input out of bounds");
|
HandleError("Setting input out of bounds");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (inputsSetMask[bindingSlot]) {
|
if (inputsSetMask[bindingSlot]) {
|
||||||
device->HandleError("Setting already set input");
|
HandleError("Setting already set input");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#define BACKEND_COMMON_INPUTSTATE_H_
|
#define BACKEND_COMMON_INPUTSTATE_H_
|
||||||
|
|
||||||
#include "Forward.h"
|
#include "Forward.h"
|
||||||
|
#include "Builder.h"
|
||||||
#include "RefCounted.h"
|
#include "RefCounted.h"
|
||||||
|
|
||||||
#include "nxt/nxtcpp.h"
|
#include "nxt/nxtcpp.h"
|
||||||
|
@ -56,12 +57,10 @@ namespace backend {
|
||||||
std::array<InputInfo, kMaxVertexInputs> inputInfos;
|
std::array<InputInfo, kMaxVertexInputs> inputInfos;
|
||||||
};
|
};
|
||||||
|
|
||||||
class InputStateBuilder : public RefCounted {
|
class InputStateBuilder : public Builder {
|
||||||
public:
|
public:
|
||||||
InputStateBuilder(DeviceBase* device);
|
InputStateBuilder(DeviceBase* device);
|
||||||
|
|
||||||
bool WasConsumed() const;
|
|
||||||
|
|
||||||
// NXT API
|
// NXT API
|
||||||
InputStateBase* GetResult();
|
InputStateBase* GetResult();
|
||||||
void SetAttribute(uint32_t shaderLocation, uint32_t bindingSlot,
|
void SetAttribute(uint32_t shaderLocation, uint32_t bindingSlot,
|
||||||
|
@ -72,12 +71,10 @@ namespace backend {
|
||||||
private:
|
private:
|
||||||
friend class InputStateBase;
|
friend class InputStateBase;
|
||||||
|
|
||||||
DeviceBase* device;
|
|
||||||
std::bitset<kMaxVertexAttributes> attributesSetMask;
|
std::bitset<kMaxVertexAttributes> attributesSetMask;
|
||||||
std::array<InputStateBase::AttributeInfo, kMaxVertexAttributes> attributeInfos;
|
std::array<InputStateBase::AttributeInfo, kMaxVertexAttributes> attributeInfos;
|
||||||
std::bitset<kMaxVertexInputs> inputsSetMask;
|
std::bitset<kMaxVertexInputs> inputsSetMask;
|
||||||
std::array<InputStateBase::InputInfo, kMaxVertexInputs> inputInfos;
|
std::array<InputStateBase::InputInfo, kMaxVertexInputs> inputInfos;
|
||||||
bool consumed = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ namespace backend {
|
||||||
|
|
||||||
if (stageMask != (nxt::ShaderStageBit::Vertex | nxt::ShaderStageBit::Fragment) &&
|
if (stageMask != (nxt::ShaderStageBit::Vertex | nxt::ShaderStageBit::Fragment) &&
|
||||||
stageMask != nxt::ShaderStageBit::Compute) {
|
stageMask != nxt::ShaderStageBit::Compute) {
|
||||||
device->HandleError("Wrong combination of stage for pipeline");
|
builder->HandleError("Wrong combination of stage for pipeline");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ namespace backend {
|
||||||
|
|
||||||
for (auto stageBit : IterateStages(builder->stageMask)) {
|
for (auto stageBit : IterateStages(builder->stageMask)) {
|
||||||
if (!builder->stages[stageBit].module->IsCompatibleWithPipelineLayout(layout.Get())) {
|
if (!builder->stages[stageBit].module->IsCompatibleWithPipelineLayout(layout.Get())) {
|
||||||
device->HandleError("Stage not compatible with layout");
|
builder->HandleError("Stage not compatible with layout");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ namespace backend {
|
||||||
|
|
||||||
if (!IsCompute()) {
|
if (!IsCompute()) {
|
||||||
if ((builder->stages[nxt::ShaderStage::Vertex].module->GetUsedVertexAttributes() & ~inputState->GetAttributesSetMask()).any()) {
|
if ((builder->stages[nxt::ShaderStage::Vertex].module->GetUsedVertexAttributes() & ~inputState->GetAttributesSetMask()).any()) {
|
||||||
device->HandleError("Pipeline vertex stage uses inputs not in the input state");
|
builder->HandleError("Pipeline vertex stage uses inputs not in the input state");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -90,11 +90,7 @@ namespace backend {
|
||||||
// PipelineBuilder
|
// PipelineBuilder
|
||||||
|
|
||||||
PipelineBuilder::PipelineBuilder(DeviceBase* device)
|
PipelineBuilder::PipelineBuilder(DeviceBase* device)
|
||||||
: device(device), stageMask(static_cast<nxt::ShaderStageBit>(0)) {
|
: Builder(device), stageMask(static_cast<nxt::ShaderStageBit>(0)) {
|
||||||
}
|
|
||||||
|
|
||||||
bool PipelineBuilder::WasConsumed() const {
|
|
||||||
return consumed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const PipelineBuilder::StageInfo& PipelineBuilder::GetStageInfo(nxt::ShaderStage stage) const {
|
const PipelineBuilder::StageInfo& PipelineBuilder::GetStageInfo(nxt::ShaderStage stage) const {
|
||||||
|
@ -111,7 +107,7 @@ namespace backend {
|
||||||
inputState = device->CreateInputStateBuilder()->GetResult();
|
inputState = device->CreateInputStateBuilder()->GetResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
consumed = true;
|
MarkConsumed();
|
||||||
return device->CreatePipeline(this);
|
return device->CreatePipeline(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,18 +117,18 @@ namespace backend {
|
||||||
|
|
||||||
void PipelineBuilder::SetStage(nxt::ShaderStage stage, ShaderModuleBase* module, const char* entryPoint) {
|
void PipelineBuilder::SetStage(nxt::ShaderStage stage, ShaderModuleBase* module, const char* entryPoint) {
|
||||||
if (entryPoint != std::string("main")) {
|
if (entryPoint != std::string("main")) {
|
||||||
device->HandleError("Currently the entry point has to be main()");
|
HandleError("Currently the entry point has to be main()");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stage != module->GetExecutionModel()) {
|
if (stage != module->GetExecutionModel()) {
|
||||||
device->HandleError("Setting module with wrong execution model");
|
HandleError("Setting module with wrong execution model");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
nxt::ShaderStageBit bit = StageBit(stage);
|
nxt::ShaderStageBit bit = StageBit(stage);
|
||||||
if (stageMask & bit) {
|
if (stageMask & bit) {
|
||||||
device->HandleError("Setting already set stage");
|
HandleError("Setting already set stage");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
stageMask |= bit;
|
stageMask |= bit;
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#define BACKEND_COMMON_PIPELINE_H_
|
#define BACKEND_COMMON_PIPELINE_H_
|
||||||
|
|
||||||
#include "Forward.h"
|
#include "Forward.h"
|
||||||
|
#include "Builder.h"
|
||||||
#include "PerStage.h"
|
#include "PerStage.h"
|
||||||
#include "RefCounted.h"
|
#include "RefCounted.h"
|
||||||
|
|
||||||
|
@ -58,12 +59,10 @@ namespace backend {
|
||||||
Ref<InputStateBase> inputState;
|
Ref<InputStateBase> inputState;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PipelineBuilder : public RefCounted {
|
class PipelineBuilder : public Builder {
|
||||||
public:
|
public:
|
||||||
PipelineBuilder(DeviceBase* device);
|
PipelineBuilder(DeviceBase* device);
|
||||||
|
|
||||||
bool WasConsumed() const;
|
|
||||||
|
|
||||||
struct StageInfo {
|
struct StageInfo {
|
||||||
std::string entryPoint;
|
std::string entryPoint;
|
||||||
Ref<ShaderModuleBase> module;
|
Ref<ShaderModuleBase> module;
|
||||||
|
@ -79,12 +78,10 @@ namespace backend {
|
||||||
private:
|
private:
|
||||||
friend class PipelineBase;
|
friend class PipelineBase;
|
||||||
|
|
||||||
DeviceBase* device;
|
|
||||||
Ref<PipelineLayoutBase> layout;
|
Ref<PipelineLayoutBase> layout;
|
||||||
nxt::ShaderStageBit stageMask;
|
nxt::ShaderStageBit stageMask;
|
||||||
PerStage<StageInfo> stages;
|
PerStage<StageInfo> stages;
|
||||||
Ref<InputStateBase> inputState;
|
Ref<InputStateBase> inputState;
|
||||||
bool consumed = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,11 +36,7 @@ namespace backend {
|
||||||
|
|
||||||
// PipelineLayoutBuilder
|
// PipelineLayoutBuilder
|
||||||
|
|
||||||
PipelineLayoutBuilder::PipelineLayoutBuilder(DeviceBase* device) : device(device) {
|
PipelineLayoutBuilder::PipelineLayoutBuilder(DeviceBase* device) : Builder(device) {
|
||||||
}
|
|
||||||
|
|
||||||
bool PipelineLayoutBuilder::WasConsumed() const {
|
|
||||||
return consumed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PipelineLayoutBase* PipelineLayoutBuilder::GetResult() {
|
PipelineLayoutBase* PipelineLayoutBuilder::GetResult() {
|
||||||
|
@ -52,17 +48,17 @@ namespace backend {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
consumed = true;
|
MarkConsumed();
|
||||||
return device->CreatePipelineLayout(this);
|
return device->CreatePipelineLayout(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PipelineLayoutBuilder::SetBindGroupLayout(uint32_t groupIndex, BindGroupLayoutBase* layout) {
|
void PipelineLayoutBuilder::SetBindGroupLayout(uint32_t groupIndex, BindGroupLayoutBase* layout) {
|
||||||
if (groupIndex >= kMaxBindGroups) {
|
if (groupIndex >= kMaxBindGroups) {
|
||||||
device->HandleError("groupIndex is over the maximum allowed");
|
HandleError("groupIndex is over the maximum allowed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (mask[groupIndex]) {
|
if (mask[groupIndex]) {
|
||||||
device->HandleError("Bind group layout already specified");
|
HandleError("Bind group layout already specified");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#define BACKEND_COMMON_PIPELINELAYOUT_H_
|
#define BACKEND_COMMON_PIPELINELAYOUT_H_
|
||||||
|
|
||||||
#include "Forward.h"
|
#include "Forward.h"
|
||||||
|
#include "Builder.h"
|
||||||
#include "RefCounted.h"
|
#include "RefCounted.h"
|
||||||
|
|
||||||
#include "nxt/nxtcpp.h"
|
#include "nxt/nxtcpp.h"
|
||||||
|
@ -39,12 +40,10 @@ namespace backend {
|
||||||
std::bitset<kMaxBindGroups> mask;
|
std::bitset<kMaxBindGroups> mask;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PipelineLayoutBuilder : public RefCounted {
|
class PipelineLayoutBuilder : public Builder {
|
||||||
public:
|
public:
|
||||||
PipelineLayoutBuilder(DeviceBase* device);
|
PipelineLayoutBuilder(DeviceBase* device);
|
||||||
|
|
||||||
bool WasConsumed() const;
|
|
||||||
|
|
||||||
// NXT API
|
// NXT API
|
||||||
PipelineLayoutBase* GetResult();
|
PipelineLayoutBase* GetResult();
|
||||||
void SetBindGroupLayout(uint32_t groupIndex, BindGroupLayoutBase* layout);
|
void SetBindGroupLayout(uint32_t groupIndex, BindGroupLayoutBase* layout);
|
||||||
|
@ -52,10 +51,8 @@ namespace backend {
|
||||||
private:
|
private:
|
||||||
friend class PipelineLayoutBase;
|
friend class PipelineLayoutBase;
|
||||||
|
|
||||||
DeviceBase* device;
|
|
||||||
BindGroupLayoutArray bindGroupLayouts;
|
BindGroupLayoutArray bindGroupLayouts;
|
||||||
std::bitset<kMaxBindGroups> mask;
|
std::bitset<kMaxBindGroups> mask;
|
||||||
bool consumed = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,15 +27,11 @@ namespace backend {
|
||||||
|
|
||||||
// QueueBuilder
|
// QueueBuilder
|
||||||
|
|
||||||
QueueBuilder::QueueBuilder(DeviceBase* device) : device(device) {
|
QueueBuilder::QueueBuilder(DeviceBase* device) : Builder(device) {
|
||||||
}
|
|
||||||
|
|
||||||
bool QueueBuilder::WasConsumed() const {
|
|
||||||
return consumed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QueueBase* QueueBuilder::GetResult() {
|
QueueBase* QueueBuilder::GetResult() {
|
||||||
consumed = true;
|
MarkConsumed();
|
||||||
return device->CreateQueue(this);
|
return device->CreateQueue(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#define BACKEND_COMMON_QUEUE_H_
|
#define BACKEND_COMMON_QUEUE_H_
|
||||||
|
|
||||||
#include "Forward.h"
|
#include "Forward.h"
|
||||||
|
#include "Builder.h"
|
||||||
#include "RefCounted.h"
|
#include "RefCounted.h"
|
||||||
|
|
||||||
#include "nxt/nxtcpp.h"
|
#include "nxt/nxtcpp.h"
|
||||||
|
@ -40,18 +41,12 @@ namespace backend {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class QueueBuilder : public RefCounted {
|
class QueueBuilder : public Builder {
|
||||||
public:
|
public:
|
||||||
QueueBuilder(DeviceBase* device);
|
QueueBuilder(DeviceBase* device);
|
||||||
|
|
||||||
bool WasConsumed() const;
|
|
||||||
|
|
||||||
// NXT API
|
// NXT API
|
||||||
QueueBase* GetResult();
|
QueueBase* GetResult();
|
||||||
|
|
||||||
private:
|
|
||||||
DeviceBase* device;
|
|
||||||
bool consumed = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,8 +28,7 @@ namespace backend {
|
||||||
enum SamplerSetProperties {
|
enum SamplerSetProperties {
|
||||||
SAMPLER_PROPERTY_FILTER = 0x1,
|
SAMPLER_PROPERTY_FILTER = 0x1,
|
||||||
};
|
};
|
||||||
SamplerBuilder::SamplerBuilder(DeviceBase* device)
|
SamplerBuilder::SamplerBuilder(DeviceBase* device) : Builder(device) {
|
||||||
:device(device) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nxt::FilterMode SamplerBuilder::GetMagFilter() const {
|
nxt::FilterMode SamplerBuilder::GetMagFilter() const {
|
||||||
|
@ -44,18 +43,14 @@ namespace backend {
|
||||||
return mipMapFilter;
|
return mipMapFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SamplerBuilder::WasConsumed() const {
|
|
||||||
return consumed;
|
|
||||||
}
|
|
||||||
|
|
||||||
SamplerBase* SamplerBuilder::GetResult() {
|
SamplerBase* SamplerBuilder::GetResult() {
|
||||||
consumed = true;
|
MarkConsumed();
|
||||||
return device->CreateSampler(this);
|
return device->CreateSampler(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SamplerBuilder::SetFilterMode(nxt::FilterMode magFilter, nxt::FilterMode minFilter, nxt::FilterMode mipMapFilter) {
|
void SamplerBuilder::SetFilterMode(nxt::FilterMode magFilter, nxt::FilterMode minFilter, nxt::FilterMode mipMapFilter) {
|
||||||
if ((propertiesSet & SAMPLER_PROPERTY_FILTER) != 0) {
|
if ((propertiesSet & SAMPLER_PROPERTY_FILTER) != 0) {
|
||||||
device->HandleError("Sampler filter property set multiple times");
|
HandleError("Sampler filter property set multiple times");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#define BACKEND_COMMON_SAMPLER_H_
|
#define BACKEND_COMMON_SAMPLER_H_
|
||||||
|
|
||||||
#include "Forward.h"
|
#include "Forward.h"
|
||||||
|
#include "Buffer.h"
|
||||||
#include "RefCounted.h"
|
#include "RefCounted.h"
|
||||||
|
|
||||||
#include "nxt/nxtcpp.h"
|
#include "nxt/nxtcpp.h"
|
||||||
|
@ -27,7 +28,7 @@ namespace backend {
|
||||||
SamplerBase(SamplerBuilder* builder);
|
SamplerBase(SamplerBuilder* builder);
|
||||||
};
|
};
|
||||||
|
|
||||||
class SamplerBuilder : public RefCounted {
|
class SamplerBuilder : public Builder {
|
||||||
public:
|
public:
|
||||||
SamplerBuilder(DeviceBase* device);
|
SamplerBuilder(DeviceBase* device);
|
||||||
|
|
||||||
|
@ -35,8 +36,6 @@ namespace backend {
|
||||||
nxt::FilterMode GetMinFilter() const;
|
nxt::FilterMode GetMinFilter() const;
|
||||||
nxt::FilterMode GetMipMapFilter() const;
|
nxt::FilterMode GetMipMapFilter() const;
|
||||||
|
|
||||||
bool WasConsumed() const;
|
|
||||||
|
|
||||||
// NXT API
|
// NXT API
|
||||||
SamplerBase* GetResult();
|
SamplerBase* GetResult();
|
||||||
void SetFilterMode(nxt::FilterMode magFilter, nxt::FilterMode minFilter, nxt::FilterMode mipMapFilter);
|
void SetFilterMode(nxt::FilterMode magFilter, nxt::FilterMode minFilter, nxt::FilterMode mipMapFilter);
|
||||||
|
@ -44,9 +43,7 @@ namespace backend {
|
||||||
private:
|
private:
|
||||||
friend class SamplerBase;
|
friend class SamplerBase;
|
||||||
|
|
||||||
DeviceBase* device;
|
|
||||||
int propertiesSet = 0;
|
int propertiesSet = 0;
|
||||||
bool consumed = false;
|
|
||||||
|
|
||||||
nxt::FilterMode magFilter = nxt::FilterMode::Nearest;
|
nxt::FilterMode magFilter = nxt::FilterMode::Nearest;
|
||||||
nxt::FilterMode minFilter = nxt::FilterMode::Nearest;
|
nxt::FilterMode minFilter = nxt::FilterMode::Nearest;
|
||||||
|
|
|
@ -28,6 +28,7 @@ namespace backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShaderModuleBase::ExtractSpirvInfo(const spirv_cross::Compiler& compiler) {
|
void ShaderModuleBase::ExtractSpirvInfo(const spirv_cross::Compiler& compiler) {
|
||||||
|
// TODO(cwallez@chromium.org): make errors here builder-level
|
||||||
const auto& resources = compiler.get_shader_resources();
|
const auto& resources = compiler.get_shader_resources();
|
||||||
|
|
||||||
switch (compiler.get_execution_model()) {
|
switch (compiler.get_execution_model()) {
|
||||||
|
@ -190,10 +191,7 @@ namespace backend {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderModuleBuilder::ShaderModuleBuilder(DeviceBase* device) : device(device) {}
|
ShaderModuleBuilder::ShaderModuleBuilder(DeviceBase* device) : Builder(device) {
|
||||||
|
|
||||||
bool ShaderModuleBuilder::WasConsumed() const {
|
|
||||||
return consumed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint32_t> ShaderModuleBuilder::AcquireSpirv() {
|
std::vector<uint32_t> ShaderModuleBuilder::AcquireSpirv() {
|
||||||
|
@ -202,11 +200,11 @@ namespace backend {
|
||||||
|
|
||||||
ShaderModuleBase* ShaderModuleBuilder::GetResult() {
|
ShaderModuleBase* ShaderModuleBuilder::GetResult() {
|
||||||
if (spirv.size() == 0) {
|
if (spirv.size() == 0) {
|
||||||
device->HandleError("Shader module needs to have the source set");
|
HandleError("Shader module needs to have the source set");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
consumed = true;
|
MarkConsumed();
|
||||||
return device->CreateShaderModule(this);
|
return device->CreateShaderModule(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#define BACKEND_COMMON_SHADERMODULE_H_
|
#define BACKEND_COMMON_SHADERMODULE_H_
|
||||||
|
|
||||||
#include "Forward.h"
|
#include "Forward.h"
|
||||||
|
#include "Builder.h"
|
||||||
#include "RefCounted.h"
|
#include "RefCounted.h"
|
||||||
|
|
||||||
#include "nxt/nxtcpp.h"
|
#include "nxt/nxtcpp.h"
|
||||||
|
@ -70,12 +71,10 @@ namespace backend {
|
||||||
nxt::ShaderStage executionModel;
|
nxt::ShaderStage executionModel;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ShaderModuleBuilder : public RefCounted {
|
class ShaderModuleBuilder : public Builder {
|
||||||
public:
|
public:
|
||||||
ShaderModuleBuilder(DeviceBase* device);
|
ShaderModuleBuilder(DeviceBase* device);
|
||||||
|
|
||||||
bool WasConsumed() const;
|
|
||||||
|
|
||||||
std::vector<uint32_t> AcquireSpirv();
|
std::vector<uint32_t> AcquireSpirv();
|
||||||
|
|
||||||
// NXT API
|
// NXT API
|
||||||
|
@ -85,9 +84,7 @@ namespace backend {
|
||||||
private:
|
private:
|
||||||
friend class ShaderModuleBase;
|
friend class ShaderModuleBase;
|
||||||
|
|
||||||
DeviceBase* device;
|
|
||||||
std::vector<uint32_t> spirv;
|
std::vector<uint32_t> spirv;
|
||||||
bool consumed = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,35 +118,31 @@ namespace backend {
|
||||||
};
|
};
|
||||||
|
|
||||||
TextureBuilder::TextureBuilder(DeviceBase* device)
|
TextureBuilder::TextureBuilder(DeviceBase* device)
|
||||||
: device(device) {
|
: Builder(device) {
|
||||||
}
|
|
||||||
|
|
||||||
bool TextureBuilder::WasConsumed() const {
|
|
||||||
return consumed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureBase* TextureBuilder::GetResult() {
|
TextureBase* TextureBuilder::GetResult() {
|
||||||
constexpr int allProperties = TEXTURE_PROPERTY_DIMENSION | TEXTURE_PROPERTY_EXTENT |
|
constexpr int allProperties = TEXTURE_PROPERTY_DIMENSION | TEXTURE_PROPERTY_EXTENT |
|
||||||
TEXTURE_PROPERTY_FORMAT | TEXTURE_PROPERTY_MIP_LEVELS | TEXTURE_PROPERTY_ALLOWED_USAGE;
|
TEXTURE_PROPERTY_FORMAT | TEXTURE_PROPERTY_MIP_LEVELS | TEXTURE_PROPERTY_ALLOWED_USAGE;
|
||||||
if ((propertiesSet & allProperties) != allProperties) {
|
if ((propertiesSet & allProperties) != allProperties) {
|
||||||
device->HandleError("Texture missing properties");
|
HandleError("Texture missing properties");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!TextureBase::IsUsagePossible(allowedUsage, currentUsage)) {
|
if (!TextureBase::IsUsagePossible(allowedUsage, currentUsage)) {
|
||||||
device->HandleError("Initial texture usage is not allowed");
|
HandleError("Initial texture usage is not allowed");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(cwallez@chromium.org): check stuff based on the dimension
|
// TODO(cwallez@chromium.org): check stuff based on the dimension
|
||||||
|
|
||||||
consumed = true;
|
MarkConsumed();
|
||||||
return device->CreateTexture(this);
|
return device->CreateTexture(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureBuilder::SetDimension(nxt::TextureDimension dimension) {
|
void TextureBuilder::SetDimension(nxt::TextureDimension dimension) {
|
||||||
if ((propertiesSet & TEXTURE_PROPERTY_DIMENSION) != 0) {
|
if ((propertiesSet & TEXTURE_PROPERTY_DIMENSION) != 0) {
|
||||||
device->HandleError("Texture dimension property set multiple times");
|
HandleError("Texture dimension property set multiple times");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,12 +152,12 @@ namespace backend {
|
||||||
|
|
||||||
void TextureBuilder::SetExtent(uint32_t width, uint32_t height, uint32_t depth) {
|
void TextureBuilder::SetExtent(uint32_t width, uint32_t height, uint32_t depth) {
|
||||||
if ((propertiesSet & TEXTURE_PROPERTY_EXTENT) != 0) {
|
if ((propertiesSet & TEXTURE_PROPERTY_EXTENT) != 0) {
|
||||||
device->HandleError("Texture extent property set multiple times");
|
HandleError("Texture extent property set multiple times");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (width == 0 || height == 0 || depth == 0) {
|
if (width == 0 || height == 0 || depth == 0) {
|
||||||
device->HandleError("Cannot create an empty texture");
|
HandleError("Cannot create an empty texture");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,7 +169,7 @@ namespace backend {
|
||||||
|
|
||||||
void TextureBuilder::SetFormat(nxt::TextureFormat format) {
|
void TextureBuilder::SetFormat(nxt::TextureFormat format) {
|
||||||
if ((propertiesSet & TEXTURE_PROPERTY_FORMAT) != 0) {
|
if ((propertiesSet & TEXTURE_PROPERTY_FORMAT) != 0) {
|
||||||
device->HandleError("Texture format property set multiple times");
|
HandleError("Texture format property set multiple times");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,7 +179,7 @@ namespace backend {
|
||||||
|
|
||||||
void TextureBuilder::SetMipLevels(uint32_t numMipLevels) {
|
void TextureBuilder::SetMipLevels(uint32_t numMipLevels) {
|
||||||
if ((propertiesSet & TEXTURE_PROPERTY_MIP_LEVELS) != 0) {
|
if ((propertiesSet & TEXTURE_PROPERTY_MIP_LEVELS) != 0) {
|
||||||
device->HandleError("Texture mip levels property set multiple times");
|
HandleError("Texture mip levels property set multiple times");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,7 +189,7 @@ namespace backend {
|
||||||
|
|
||||||
void TextureBuilder::SetAllowedUsage(nxt::TextureUsageBit usage) {
|
void TextureBuilder::SetAllowedUsage(nxt::TextureUsageBit usage) {
|
||||||
if ((propertiesSet & TEXTURE_PROPERTY_ALLOWED_USAGE) != 0) {
|
if ((propertiesSet & TEXTURE_PROPERTY_ALLOWED_USAGE) != 0) {
|
||||||
device->HandleError("Texture allowed usage property set multiple times");
|
HandleError("Texture allowed usage property set multiple times");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,7 +199,7 @@ namespace backend {
|
||||||
|
|
||||||
void TextureBuilder::SetInitialUsage(nxt::TextureUsageBit usage) {
|
void TextureBuilder::SetInitialUsage(nxt::TextureUsageBit usage) {
|
||||||
if ((propertiesSet & TEXTURE_PROPERTY_INITIAL_USAGE) != 0) {
|
if ((propertiesSet & TEXTURE_PROPERTY_INITIAL_USAGE) != 0) {
|
||||||
device->HandleError("Texture initial usage property set multiple times");
|
HandleError("Texture initial usage property set multiple times");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,15 +220,11 @@ namespace backend {
|
||||||
// TextureViewBuilder
|
// TextureViewBuilder
|
||||||
|
|
||||||
TextureViewBuilder::TextureViewBuilder(DeviceBase* device, TextureBase* texture)
|
TextureViewBuilder::TextureViewBuilder(DeviceBase* device, TextureBase* texture)
|
||||||
: device(device), texture(texture) {
|
: Builder(device), texture(texture) {
|
||||||
}
|
|
||||||
|
|
||||||
bool TextureViewBuilder::WasConsumed() const {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureViewBase* TextureViewBuilder::GetResult() {
|
TextureViewBase* TextureViewBuilder::GetResult() {
|
||||||
consumed = true;
|
MarkConsumed();
|
||||||
return device->CreateTextureView(this);
|
return device->CreateTextureView(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#define BACKEND_COMMON_TEXTURE_H_
|
#define BACKEND_COMMON_TEXTURE_H_
|
||||||
|
|
||||||
#include "Forward.h"
|
#include "Forward.h"
|
||||||
|
#include "Builder.h"
|
||||||
#include "RefCounted.h"
|
#include "RefCounted.h"
|
||||||
|
|
||||||
#include "nxt/nxtcpp.h"
|
#include "nxt/nxtcpp.h"
|
||||||
|
@ -59,12 +60,10 @@ namespace backend {
|
||||||
bool frozen = false;
|
bool frozen = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TextureBuilder : public RefCounted {
|
class TextureBuilder : public Builder {
|
||||||
public:
|
public:
|
||||||
TextureBuilder(DeviceBase* device);
|
TextureBuilder(DeviceBase* device);
|
||||||
|
|
||||||
bool WasConsumed() const;
|
|
||||||
|
|
||||||
// NXT API
|
// NXT API
|
||||||
TextureBase* GetResult();
|
TextureBase* GetResult();
|
||||||
void SetDimension(nxt::TextureDimension dimension);
|
void SetDimension(nxt::TextureDimension dimension);
|
||||||
|
@ -77,9 +76,7 @@ namespace backend {
|
||||||
private:
|
private:
|
||||||
friend class TextureBase;
|
friend class TextureBase;
|
||||||
|
|
||||||
DeviceBase* device;
|
|
||||||
int propertiesSet = 0;
|
int propertiesSet = 0;
|
||||||
bool consumed = false;
|
|
||||||
|
|
||||||
nxt::TextureDimension dimension;
|
nxt::TextureDimension dimension;
|
||||||
uint32_t width, height, depth;
|
uint32_t width, height, depth;
|
||||||
|
@ -99,20 +96,16 @@ namespace backend {
|
||||||
Ref<TextureBase> texture;
|
Ref<TextureBase> texture;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TextureViewBuilder : public RefCounted {
|
class TextureViewBuilder : public Builder {
|
||||||
public:
|
public:
|
||||||
TextureViewBuilder(DeviceBase* device, TextureBase* texture);
|
TextureViewBuilder(DeviceBase* device, TextureBase* texture);
|
||||||
|
|
||||||
bool WasConsumed() const;
|
|
||||||
|
|
||||||
// NXT API
|
// NXT API
|
||||||
TextureViewBase* GetResult();
|
TextureViewBase* GetResult();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class TextureViewBase;
|
friend class TextureViewBase;
|
||||||
|
|
||||||
DeviceBase* device;
|
|
||||||
bool consumed = false;
|
|
||||||
Ref<TextureBase> texture;
|
Ref<TextureBase> texture;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -678,7 +678,7 @@ namespace metal {
|
||||||
newComputePipelineStateWithFunction:function error:&error];
|
newComputePipelineStateWithFunction:function error:&error];
|
||||||
if (error != nil) {
|
if (error != nil) {
|
||||||
NSLog(@" error => %@", error);
|
NSLog(@" error => %@", error);
|
||||||
device->HandleError("Error creating pipeline state");
|
builder->HandleError("Error creating pipeline state");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -720,7 +720,7 @@ namespace metal {
|
||||||
newRenderPipelineStateWithDescriptor:descriptor error:&error];
|
newRenderPipelineStateWithDescriptor:descriptor error:&error];
|
||||||
if (error != nil) {
|
if (error != nil) {
|
||||||
NSLog(@" error => %@", error);
|
NSLog(@" error => %@", error);
|
||||||
device->HandleError("Error creating pipeline state");
|
builder->HandleError("Error creating pipeline state");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -898,7 +898,7 @@ namespace metal {
|
||||||
mtlLibrary = [device->GetMTLDevice() newLibraryWithSource:mslSource options:nil error:&error];
|
mtlLibrary = [device->GetMTLDevice() newLibraryWithSource:mslSource options:nil error:&error];
|
||||||
if (error != nil) {
|
if (error != nil) {
|
||||||
NSLog(@"MTLDevice newLibraryWithSource => %@", error);
|
NSLog(@"MTLDevice newLibraryWithSource => %@", error);
|
||||||
device->HandleError("Error creating MTLLibrary from MSL source");
|
builder->HandleError("Error creating MTLLibrary from MSL source");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue