Member rename: src/backend
This commit is contained in:
parent
b325f4d0af
commit
fbecc28ac4
|
@ -26,37 +26,37 @@ namespace backend {
|
||||||
// BindGroup
|
// BindGroup
|
||||||
|
|
||||||
BindGroupBase::BindGroupBase(BindGroupBuilder* builder)
|
BindGroupBase::BindGroupBase(BindGroupBuilder* builder)
|
||||||
: layout(std::move(builder->layout)), usage(builder->usage), bindings(std::move(builder->bindings)) {
|
: mLayout(std::move(builder->mLayout)), mUsage(builder->mUsage), mBindings(std::move(builder->mBindings)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const BindGroupLayoutBase* BindGroupBase::GetLayout() const {
|
const BindGroupLayoutBase* BindGroupBase::GetLayout() const {
|
||||||
return layout.Get();
|
return mLayout.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
nxt::BindGroupUsage BindGroupBase::GetUsage() const {
|
nxt::BindGroupUsage BindGroupBase::GetUsage() const {
|
||||||
return usage;
|
return mUsage;
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferViewBase* BindGroupBase::GetBindingAsBufferView(size_t binding) {
|
BufferViewBase* BindGroupBase::GetBindingAsBufferView(size_t binding) {
|
||||||
ASSERT(binding < kMaxBindingsPerGroup);
|
ASSERT(binding < kMaxBindingsPerGroup);
|
||||||
ASSERT(layout->GetBindingInfo().mask[binding]);
|
ASSERT(mLayout->GetBindingInfo().mask[binding]);
|
||||||
ASSERT(layout->GetBindingInfo().types[binding] == nxt::BindingType::UniformBuffer ||
|
ASSERT(mLayout->GetBindingInfo().types[binding] == nxt::BindingType::UniformBuffer ||
|
||||||
layout->GetBindingInfo().types[binding] == nxt::BindingType::StorageBuffer);
|
mLayout->GetBindingInfo().types[binding] == nxt::BindingType::StorageBuffer);
|
||||||
return reinterpret_cast<BufferViewBase*>(bindings[binding].Get());
|
return reinterpret_cast<BufferViewBase*>(mBindings[binding].Get());
|
||||||
}
|
}
|
||||||
|
|
||||||
SamplerBase* BindGroupBase::GetBindingAsSampler(size_t binding) {
|
SamplerBase* BindGroupBase::GetBindingAsSampler(size_t binding) {
|
||||||
ASSERT(binding < kMaxBindingsPerGroup);
|
ASSERT(binding < kMaxBindingsPerGroup);
|
||||||
ASSERT(layout->GetBindingInfo().mask[binding]);
|
ASSERT(mLayout->GetBindingInfo().mask[binding]);
|
||||||
ASSERT(layout->GetBindingInfo().types[binding] == nxt::BindingType::Sampler);
|
ASSERT(mLayout->GetBindingInfo().types[binding] == nxt::BindingType::Sampler);
|
||||||
return reinterpret_cast<SamplerBase*>(bindings[binding].Get());
|
return reinterpret_cast<SamplerBase*>(mBindings[binding].Get());
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureViewBase* BindGroupBase::GetBindingAsTextureView(size_t binding) {
|
TextureViewBase* BindGroupBase::GetBindingAsTextureView(size_t binding) {
|
||||||
ASSERT(binding < kMaxBindingsPerGroup);
|
ASSERT(binding < kMaxBindingsPerGroup);
|
||||||
ASSERT(layout->GetBindingInfo().mask[binding]);
|
ASSERT(mLayout->GetBindingInfo().mask[binding]);
|
||||||
ASSERT(layout->GetBindingInfo().types[binding] == nxt::BindingType::SampledTexture);
|
ASSERT(mLayout->GetBindingInfo().types[binding] == nxt::BindingType::SampledTexture);
|
||||||
return reinterpret_cast<TextureViewBase*>(bindings[binding].Get());
|
return reinterpret_cast<TextureViewBase*>(mBindings[binding].Get());
|
||||||
}
|
}
|
||||||
|
|
||||||
// BindGroupBuilder
|
// BindGroupBuilder
|
||||||
|
@ -71,37 +71,37 @@ namespace backend {
|
||||||
|
|
||||||
BindGroupBase* BindGroupBuilder::GetResultImpl() {
|
BindGroupBase* BindGroupBuilder::GetResultImpl() {
|
||||||
constexpr int allProperties = BINDGROUP_PROPERTY_USAGE | BINDGROUP_PROPERTY_LAYOUT;
|
constexpr int allProperties = BINDGROUP_PROPERTY_USAGE | BINDGROUP_PROPERTY_LAYOUT;
|
||||||
if ((propertiesSet & allProperties) != allProperties) {
|
if ((mPropertiesSet & allProperties) != allProperties) {
|
||||||
HandleError("Bindgroup missing properties");
|
HandleError("Bindgroup missing properties");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setMask != layout->GetBindingInfo().mask) {
|
if (mSetMask != mLayout->GetBindingInfo().mask) {
|
||||||
HandleError("Bindgroup missing bindings");
|
HandleError("Bindgroup missing bindings");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return device->CreateBindGroup(this);
|
return mDevice->CreateBindGroup(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BindGroupBuilder::SetLayout(BindGroupLayoutBase* layout) {
|
void BindGroupBuilder::SetLayout(BindGroupLayoutBase* layout) {
|
||||||
if ((propertiesSet & BINDGROUP_PROPERTY_LAYOUT) != 0) {
|
if ((mPropertiesSet & BINDGROUP_PROPERTY_LAYOUT) != 0) {
|
||||||
HandleError("Bindgroup layout property set multiple times");
|
HandleError("Bindgroup layout property set multiple times");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->layout = layout;
|
mLayout = layout;
|
||||||
propertiesSet |= BINDGROUP_PROPERTY_LAYOUT;
|
mPropertiesSet |= BINDGROUP_PROPERTY_LAYOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BindGroupBuilder::SetUsage(nxt::BindGroupUsage usage) {
|
void BindGroupBuilder::SetUsage(nxt::BindGroupUsage usage) {
|
||||||
if ((propertiesSet & BINDGROUP_PROPERTY_USAGE) != 0) {
|
if ((mPropertiesSet & BINDGROUP_PROPERTY_USAGE) != 0) {
|
||||||
HandleError("Bindgroup usage property set multiple times");
|
HandleError("Bindgroup usage property set multiple times");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->usage = usage;
|
mUsage = usage;
|
||||||
propertiesSet |= BINDGROUP_PROPERTY_USAGE;
|
mPropertiesSet |= BINDGROUP_PROPERTY_USAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BindGroupBuilder::SetBufferViews(uint32_t start, uint32_t count, BufferViewBase* const * bufferViews) {
|
void BindGroupBuilder::SetBufferViews(uint32_t start, uint32_t count, BufferViewBase* const * bufferViews) {
|
||||||
|
@ -109,7 +109,7 @@ namespace backend {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& layoutInfo = layout->GetBindingInfo();
|
const auto& layoutInfo = mLayout->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) {
|
||||||
nxt::BufferUsageBit requiredBit = nxt::BufferUsageBit::None;
|
nxt::BufferUsageBit requiredBit = nxt::BufferUsageBit::None;
|
||||||
switch (layoutInfo.types[i]) {
|
switch (layoutInfo.types[i]) {
|
||||||
|
@ -146,7 +146,7 @@ namespace backend {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& layoutInfo = layout->GetBindingInfo();
|
const auto& layoutInfo = mLayout->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) {
|
||||||
HandleError("Setting binding for a wrong layout binding type");
|
HandleError("Setting binding for a wrong layout binding type");
|
||||||
|
@ -162,7 +162,7 @@ namespace backend {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& layoutInfo = layout->GetBindingInfo();
|
const auto& layoutInfo = mLayout->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) {
|
||||||
HandleError("Setting binding for a wrong layout binding type");
|
HandleError("Setting binding for a wrong layout binding type");
|
||||||
|
@ -180,8 +180,8 @@ namespace backend {
|
||||||
|
|
||||||
void BindGroupBuilder::SetBindingsBase(uint32_t start, uint32_t count, RefCounted* const * objects) {
|
void BindGroupBuilder::SetBindingsBase(uint32_t start, uint32_t count, RefCounted* const * objects) {
|
||||||
for (size_t i = start, j = 0; i < start + count; ++i, ++j) {
|
for (size_t i = start, j = 0; i < start + count; ++i, ++j) {
|
||||||
setMask.set(i);
|
mSetMask.set(i);
|
||||||
bindings[i] = objects[j];
|
mBindings[i] = objects[j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,14 +191,14 @@ namespace backend {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((propertiesSet & BINDGROUP_PROPERTY_LAYOUT) == 0) {
|
if ((mPropertiesSet & BINDGROUP_PROPERTY_LAYOUT) == 0) {
|
||||||
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 = mLayout->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 (mSetMask[i]) {
|
||||||
HandleError("Setting already set binding");
|
HandleError("Setting already set binding");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,9 +39,9 @@ namespace backend {
|
||||||
TextureViewBase* GetBindingAsTextureView(size_t binding);
|
TextureViewBase* GetBindingAsTextureView(size_t binding);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ref<BindGroupLayoutBase> layout;
|
Ref<BindGroupLayoutBase> mLayout;
|
||||||
nxt::BindGroupUsage usage;
|
nxt::BindGroupUsage mUsage;
|
||||||
std::array<Ref<RefCounted>, kMaxBindingsPerGroup> bindings;
|
std::array<Ref<RefCounted>, kMaxBindingsPerGroup> mBindings;
|
||||||
};
|
};
|
||||||
|
|
||||||
class BindGroupBuilder : public Builder<BindGroupBase> {
|
class BindGroupBuilder : public Builder<BindGroupBase> {
|
||||||
|
@ -80,12 +80,12 @@ 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);
|
||||||
|
|
||||||
std::bitset<kMaxBindingsPerGroup> setMask;
|
std::bitset<kMaxBindingsPerGroup> mSetMask;
|
||||||
int propertiesSet = 0;
|
int mPropertiesSet = 0;
|
||||||
|
|
||||||
Ref<BindGroupLayoutBase> layout;
|
Ref<BindGroupLayoutBase> mLayout;
|
||||||
nxt::BindGroupUsage usage;
|
nxt::BindGroupUsage mUsage;
|
||||||
std::array<Ref<RefCounted>, kMaxBindingsPerGroup> bindings;
|
std::array<Ref<RefCounted>, kMaxBindingsPerGroup> mBindings;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,18 +77,18 @@ namespace backend {
|
||||||
// BindGroupLayoutBase
|
// BindGroupLayoutBase
|
||||||
|
|
||||||
BindGroupLayoutBase::BindGroupLayoutBase(BindGroupLayoutBuilder* builder, bool blueprint)
|
BindGroupLayoutBase::BindGroupLayoutBase(BindGroupLayoutBuilder* builder, bool blueprint)
|
||||||
: device(builder->device), bindingInfo(builder->bindingInfo), blueprint(blueprint) {
|
: mDevice(builder->mDevice), mBindingInfo(builder->mBindingInfo), mIsBlueprint(blueprint) {
|
||||||
}
|
}
|
||||||
|
|
||||||
BindGroupLayoutBase::~BindGroupLayoutBase() {
|
BindGroupLayoutBase::~BindGroupLayoutBase() {
|
||||||
// Do not register the actual cached object if we are a blueprint
|
// Do not register the actual cached object if we are a blueprint
|
||||||
if (!blueprint) {
|
if (!mIsBlueprint) {
|
||||||
device->UncacheBindGroupLayout(this);
|
mDevice->UncacheBindGroupLayout(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const BindGroupLayoutBase::LayoutBindingInfo& BindGroupLayoutBase::GetBindingInfo() const {
|
const BindGroupLayoutBase::LayoutBindingInfo& BindGroupLayoutBase::GetBindingInfo() const {
|
||||||
return bindingInfo;
|
return mBindingInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
// BindGroupLayoutBuilder
|
// BindGroupLayoutBuilder
|
||||||
|
@ -97,13 +97,13 @@ namespace backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
const BindGroupLayoutBase::LayoutBindingInfo& BindGroupLayoutBuilder::GetBindingInfo() const {
|
const BindGroupLayoutBase::LayoutBindingInfo& BindGroupLayoutBuilder::GetBindingInfo() const {
|
||||||
return bindingInfo;
|
return mBindingInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
BindGroupLayoutBase* BindGroupLayoutBuilder::GetResultImpl() {
|
BindGroupLayoutBase* BindGroupLayoutBuilder::GetResultImpl() {
|
||||||
BindGroupLayoutBase blueprint(this, true);
|
BindGroupLayoutBase blueprint(this, true);
|
||||||
|
|
||||||
auto* result = device->GetOrCreateBindGroupLayout(&blueprint, this);
|
auto* result = mDevice->GetOrCreateBindGroupLayout(&blueprint, this);
|
||||||
result->Reference();
|
result->Reference();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -114,16 +114,16 @@ namespace backend {
|
||||||
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 (mBindingInfo.mask[i]) {
|
||||||
HandleError("Setting already set binding type");
|
HandleError("Setting already set binding type");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = start; i < start + count; i++) {
|
for (size_t i = start; i < start + count; i++) {
|
||||||
bindingInfo.mask.set(i);
|
mBindingInfo.mask.set(i);
|
||||||
bindingInfo.visibilities[i] = visibility;
|
mBindingInfo.visibilities[i] = visibility;
|
||||||
bindingInfo.types[i] = bindingType;
|
mBindingInfo.types[i] = bindingType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,9 +40,9 @@ namespace backend {
|
||||||
const LayoutBindingInfo& GetBindingInfo() const;
|
const LayoutBindingInfo& GetBindingInfo() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DeviceBase* device;
|
DeviceBase* mDevice;
|
||||||
LayoutBindingInfo bindingInfo;
|
LayoutBindingInfo mBindingInfo;
|
||||||
bool blueprint = false;
|
bool mIsBlueprint = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class BindGroupLayoutBuilder : public Builder<BindGroupLayoutBase> {
|
class BindGroupLayoutBuilder : public Builder<BindGroupLayoutBase> {
|
||||||
|
@ -59,7 +59,7 @@ namespace backend {
|
||||||
|
|
||||||
BindGroupLayoutBase* GetResultImpl() override;
|
BindGroupLayoutBase* GetResultImpl() override;
|
||||||
|
|
||||||
BindGroupLayoutBase::LayoutBindingInfo bindingInfo;
|
BindGroupLayoutBase::LayoutBindingInfo mBindingInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Implements the functors necessary for the unordered_set<BGL*>-based cache.
|
// Implements the functors necessary for the unordered_set<BGL*>-based cache.
|
||||||
|
|
|
@ -20,11 +20,11 @@ namespace backend {
|
||||||
|
|
||||||
// BlendStateBase
|
// BlendStateBase
|
||||||
|
|
||||||
BlendStateBase::BlendStateBase(BlendStateBuilder* builder) : blendInfo(builder->blendInfo) {
|
BlendStateBase::BlendStateBase(BlendStateBuilder* builder) : mBlendInfo(builder->mBlendInfo) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const BlendStateBase::BlendInfo& BlendStateBase::GetBlendInfo() const {
|
const BlendStateBase::BlendInfo& BlendStateBase::GetBlendInfo() const {
|
||||||
return blendInfo;
|
return mBlendInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
// BlendStateBuilder
|
// BlendStateBuilder
|
||||||
|
@ -40,50 +40,50 @@ namespace backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
BlendStateBase* BlendStateBuilder::GetResultImpl() {
|
BlendStateBase* BlendStateBuilder::GetResultImpl() {
|
||||||
return device->CreateBlendState(this);
|
return mDevice->CreateBlendState(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlendStateBuilder::SetBlendEnabled(bool blendEnabled) {
|
void BlendStateBuilder::SetBlendEnabled(bool blendEnabled) {
|
||||||
if ((propertiesSet & BLEND_STATE_PROPERTY_BLEND_ENABLED) != 0) {
|
if ((mPropertiesSet & BLEND_STATE_PROPERTY_BLEND_ENABLED) != 0) {
|
||||||
HandleError("Blend enabled property set multiple times");
|
HandleError("Blend enabled property set multiple times");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
propertiesSet |= BLEND_STATE_PROPERTY_BLEND_ENABLED;
|
mPropertiesSet |= BLEND_STATE_PROPERTY_BLEND_ENABLED;
|
||||||
|
|
||||||
blendInfo.blendEnabled = blendEnabled;
|
mBlendInfo.blendEnabled = blendEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlendStateBuilder::SetAlphaBlend(nxt::BlendOperation blendOperation, nxt::BlendFactor srcFactor, nxt::BlendFactor dstFactor) {
|
void BlendStateBuilder::SetAlphaBlend(nxt::BlendOperation blendOperation, nxt::BlendFactor srcFactor, nxt::BlendFactor dstFactor) {
|
||||||
if ((propertiesSet & BLEND_STATE_PROPERTY_ALPHA_BLEND) != 0) {
|
if ((mPropertiesSet & BLEND_STATE_PROPERTY_ALPHA_BLEND) != 0) {
|
||||||
HandleError("Alpha blend property set multiple times");
|
HandleError("Alpha blend property set multiple times");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
propertiesSet |= BLEND_STATE_PROPERTY_ALPHA_BLEND;
|
mPropertiesSet |= BLEND_STATE_PROPERTY_ALPHA_BLEND;
|
||||||
|
|
||||||
blendInfo.alphaBlend = { blendOperation, srcFactor, dstFactor };
|
mBlendInfo.alphaBlend = { blendOperation, srcFactor, dstFactor };
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlendStateBuilder::SetColorBlend(nxt::BlendOperation blendOperation, nxt::BlendFactor srcFactor, nxt::BlendFactor dstFactor) {
|
void BlendStateBuilder::SetColorBlend(nxt::BlendOperation blendOperation, nxt::BlendFactor srcFactor, nxt::BlendFactor dstFactor) {
|
||||||
if ((propertiesSet & BLEND_STATE_PROPERTY_COLOR_BLEND) != 0) {
|
if ((mPropertiesSet & BLEND_STATE_PROPERTY_COLOR_BLEND) != 0) {
|
||||||
HandleError("Color blend property set multiple times");
|
HandleError("Color blend property set multiple times");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
propertiesSet |= BLEND_STATE_PROPERTY_COLOR_BLEND;
|
mPropertiesSet |= BLEND_STATE_PROPERTY_COLOR_BLEND;
|
||||||
|
|
||||||
blendInfo.colorBlend = { blendOperation, srcFactor, dstFactor };
|
mBlendInfo.colorBlend = { blendOperation, srcFactor, dstFactor };
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlendStateBuilder::SetColorWriteMask(nxt::ColorWriteMask colorWriteMask) {
|
void BlendStateBuilder::SetColorWriteMask(nxt::ColorWriteMask colorWriteMask) {
|
||||||
if ((propertiesSet & BLEND_STATE_PROPERTY_COLOR_WRITE_MASK) != 0) {
|
if ((mPropertiesSet & BLEND_STATE_PROPERTY_COLOR_WRITE_MASK) != 0) {
|
||||||
HandleError("Color write mask property set multiple times");
|
HandleError("Color write mask property set multiple times");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
propertiesSet |= BLEND_STATE_PROPERTY_COLOR_WRITE_MASK;
|
mPropertiesSet |= BLEND_STATE_PROPERTY_COLOR_WRITE_MASK;
|
||||||
|
|
||||||
blendInfo.colorWriteMask = colorWriteMask;
|
mBlendInfo.colorWriteMask = colorWriteMask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ namespace backend {
|
||||||
const BlendInfo& GetBlendInfo() const;
|
const BlendInfo& GetBlendInfo() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BlendInfo blendInfo;
|
BlendInfo mBlendInfo;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -62,9 +62,9 @@ namespace backend {
|
||||||
|
|
||||||
BlendStateBase* GetResultImpl() override;
|
BlendStateBase* GetResultImpl() override;
|
||||||
|
|
||||||
int propertiesSet = 0;
|
int mPropertiesSet = 0;
|
||||||
|
|
||||||
BlendStateBase::BlendInfo blendInfo;
|
BlendStateBase::BlendInfo mBlendInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,53 +25,53 @@ namespace backend {
|
||||||
// Buffer
|
// Buffer
|
||||||
|
|
||||||
BufferBase::BufferBase(BufferBuilder* builder)
|
BufferBase::BufferBase(BufferBuilder* builder)
|
||||||
: device(builder->device),
|
: mDevice(builder->mDevice),
|
||||||
size(builder->size),
|
mSize(builder->mSize),
|
||||||
allowedUsage(builder->allowedUsage),
|
mAllowedUsage(builder->mAllowedUsage),
|
||||||
currentUsage(builder->currentUsage) {
|
mCurrentUsage(builder->mCurrentUsage) {
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferBase::~BufferBase() {
|
BufferBase::~BufferBase() {
|
||||||
if (mapped) {
|
if (mIsMapped) {
|
||||||
CallMapReadCallback(mapReadSerial, NXT_BUFFER_MAP_READ_STATUS_UNKNOWN, nullptr);
|
CallMapReadCallback(mMapReadSerial, NXT_BUFFER_MAP_READ_STATUS_UNKNOWN, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferViewBuilder* BufferBase::CreateBufferViewBuilder() {
|
BufferViewBuilder* BufferBase::CreateBufferViewBuilder() {
|
||||||
return new BufferViewBuilder(device, this);
|
return new BufferViewBuilder(mDevice, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
DeviceBase* BufferBase::GetDevice() {
|
DeviceBase* BufferBase::GetDevice() {
|
||||||
return device;
|
return mDevice;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t BufferBase::GetSize() const {
|
uint32_t BufferBase::GetSize() const {
|
||||||
return size;
|
return mSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
nxt::BufferUsageBit BufferBase::GetAllowedUsage() const {
|
nxt::BufferUsageBit BufferBase::GetAllowedUsage() const {
|
||||||
return allowedUsage;
|
return mAllowedUsage;
|
||||||
}
|
}
|
||||||
|
|
||||||
nxt::BufferUsageBit BufferBase::GetUsage() const {
|
nxt::BufferUsageBit BufferBase::GetUsage() const {
|
||||||
return currentUsage;
|
return mCurrentUsage;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BufferBase::CallMapReadCallback(uint32_t serial, nxtBufferMapReadStatus status, const void* pointer) {
|
void BufferBase::CallMapReadCallback(uint32_t serial, nxtBufferMapReadStatus status, const void* pointer) {
|
||||||
if (mapReadCallback && serial == mapReadSerial) {
|
if (mMapReadCallback && serial == mMapReadSerial) {
|
||||||
mapReadCallback(status, pointer, mapReadUserdata);
|
mMapReadCallback(status, pointer, mMapReadUserdata);
|
||||||
mapReadCallback = nullptr;
|
mMapReadCallback = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BufferBase::SetSubData(uint32_t start, uint32_t count, const uint32_t* data) {
|
void BufferBase::SetSubData(uint32_t start, uint32_t count, const uint32_t* data) {
|
||||||
if ((start + count) * sizeof(uint32_t) > GetSize()) {
|
if ((start + count) * sizeof(uint32_t) > GetSize()) {
|
||||||
device->HandleError("Buffer subdata out of range");
|
mDevice->HandleError("Buffer subdata out of range");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(currentUsage & nxt::BufferUsageBit::TransferDst)) {
|
if (!(mCurrentUsage & nxt::BufferUsageBit::TransferDst)) {
|
||||||
device->HandleError("Buffer needs the transfer dst usage bit");
|
mDevice->HandleError("Buffer needs the transfer dst usage bit");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,50 +80,50 @@ namespace backend {
|
||||||
|
|
||||||
void BufferBase::MapReadAsync(uint32_t start, uint32_t size, nxtBufferMapReadCallback callback, nxtCallbackUserdata userdata) {
|
void BufferBase::MapReadAsync(uint32_t start, uint32_t size, nxtBufferMapReadCallback callback, nxtCallbackUserdata userdata) {
|
||||||
if (start + size > GetSize()) {
|
if (start + size > GetSize()) {
|
||||||
device->HandleError("Buffer map read out of range");
|
mDevice->HandleError("Buffer map read out of range");
|
||||||
callback(NXT_BUFFER_MAP_READ_STATUS_ERROR, nullptr, userdata);
|
callback(NXT_BUFFER_MAP_READ_STATUS_ERROR, nullptr, userdata);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(currentUsage & nxt::BufferUsageBit::MapRead)) {
|
if (!(mCurrentUsage & nxt::BufferUsageBit::MapRead)) {
|
||||||
device->HandleError("Buffer needs the map read usage bit");
|
mDevice->HandleError("Buffer needs the map read usage bit");
|
||||||
callback(NXT_BUFFER_MAP_READ_STATUS_ERROR, nullptr, userdata);
|
callback(NXT_BUFFER_MAP_READ_STATUS_ERROR, nullptr, userdata);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mapped) {
|
if (mIsMapped) {
|
||||||
device->HandleError("Buffer already mapped");
|
mDevice->HandleError("Buffer already mapped");
|
||||||
callback(NXT_BUFFER_MAP_READ_STATUS_ERROR, nullptr, userdata);
|
callback(NXT_BUFFER_MAP_READ_STATUS_ERROR, nullptr, userdata);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(cwallez@chromium.org): what to do on wraparound? Could cause crashes.
|
// TODO(cwallez@chromium.org): what to do on wraparound? Could cause crashes.
|
||||||
mapReadSerial ++;
|
mMapReadSerial ++;
|
||||||
mapReadCallback = callback;
|
mMapReadCallback = callback;
|
||||||
mapReadUserdata = userdata;
|
mMapReadUserdata = userdata;
|
||||||
MapReadAsyncImpl(mapReadSerial, start, size);
|
MapReadAsyncImpl(mMapReadSerial, start, size);
|
||||||
mapped = true;
|
mIsMapped = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BufferBase::Unmap() {
|
void BufferBase::Unmap() {
|
||||||
if (!mapped) {
|
if (!mIsMapped) {
|
||||||
device->HandleError("Buffer wasn't mapped");
|
mDevice->HandleError("Buffer wasn't mapped");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// A map request can only be called once, so this will fire only if the request wasn't
|
// A map request can only be called once, so this will fire only if the request wasn't
|
||||||
// completed before the Unmap
|
// completed before the Unmap
|
||||||
CallMapReadCallback(mapReadSerial, NXT_BUFFER_MAP_READ_STATUS_UNKNOWN, nullptr);
|
CallMapReadCallback(mMapReadSerial, NXT_BUFFER_MAP_READ_STATUS_UNKNOWN, nullptr);
|
||||||
UnmapImpl();
|
UnmapImpl();
|
||||||
mapped = false;
|
mIsMapped = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BufferBase::IsFrozen() const {
|
bool BufferBase::IsFrozen() const {
|
||||||
return frozen;
|
return mIsFrozen;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BufferBase::HasFrozenUsage(nxt::BufferUsageBit usage) const {
|
bool BufferBase::HasFrozenUsage(nxt::BufferUsageBit usage) const {
|
||||||
return frozen && (usage & allowedUsage);
|
return mIsFrozen && (usage & mAllowedUsage);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BufferBase::IsUsagePossible(nxt::BufferUsageBit allowedUsage, nxt::BufferUsageBit usage) {
|
bool BufferBase::IsUsagePossible(nxt::BufferUsageBit allowedUsage, nxt::BufferUsageBit usage) {
|
||||||
|
@ -140,35 +140,35 @@ namespace backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BufferBase::IsTransitionPossible(nxt::BufferUsageBit usage) const {
|
bool BufferBase::IsTransitionPossible(nxt::BufferUsageBit usage) const {
|
||||||
if (frozen || mapped) {
|
if (mIsFrozen || mIsMapped) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return IsUsagePossible(allowedUsage, usage);
|
return IsUsagePossible(mAllowedUsage, usage);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BufferBase::UpdateUsageInternal(nxt::BufferUsageBit usage) {
|
void BufferBase::UpdateUsageInternal(nxt::BufferUsageBit usage) {
|
||||||
ASSERT(IsTransitionPossible(usage));
|
ASSERT(IsTransitionPossible(usage));
|
||||||
currentUsage = usage;
|
mCurrentUsage = usage;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BufferBase::TransitionUsage(nxt::BufferUsageBit usage) {
|
void BufferBase::TransitionUsage(nxt::BufferUsageBit usage) {
|
||||||
if (!IsTransitionPossible(usage)) {
|
if (!IsTransitionPossible(usage)) {
|
||||||
device->HandleError("Buffer frozen or usage not allowed");
|
mDevice->HandleError("Buffer frozen or usage not allowed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
TransitionUsageImpl(currentUsage, usage);
|
TransitionUsageImpl(mCurrentUsage, usage);
|
||||||
currentUsage = usage;
|
mCurrentUsage = usage;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BufferBase::FreezeUsage(nxt::BufferUsageBit usage) {
|
void BufferBase::FreezeUsage(nxt::BufferUsageBit usage) {
|
||||||
if (!IsTransitionPossible(usage)) {
|
if (!IsTransitionPossible(usage)) {
|
||||||
device->HandleError("Buffer frozen or usage not allowed");
|
mDevice->HandleError("Buffer frozen or usage not allowed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
allowedUsage = usage;
|
mAllowedUsage = usage;
|
||||||
TransitionUsageImpl(currentUsage, usage);
|
TransitionUsageImpl(mCurrentUsage, usage);
|
||||||
currentUsage = usage;
|
mCurrentUsage = usage;
|
||||||
frozen = true;
|
mIsFrozen = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// BufferBuilder
|
// BufferBuilder
|
||||||
|
@ -184,79 +184,79 @@ namespace backend {
|
||||||
|
|
||||||
BufferBase* BufferBuilder::GetResultImpl() {
|
BufferBase* BufferBuilder::GetResultImpl() {
|
||||||
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 ((mPropertiesSet & allProperties) != allProperties) {
|
||||||
HandleError("Buffer missing properties");
|
HandleError("Buffer missing properties");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const nxt::BufferUsageBit kMapWriteAllowedUsages = nxt::BufferUsageBit::MapWrite | nxt::BufferUsageBit::TransferSrc;
|
const nxt::BufferUsageBit kMapWriteAllowedUsages = nxt::BufferUsageBit::MapWrite | nxt::BufferUsageBit::TransferSrc;
|
||||||
if (allowedUsage & nxt::BufferUsageBit::MapWrite &&
|
if (mAllowedUsage & nxt::BufferUsageBit::MapWrite &&
|
||||||
(allowedUsage & kMapWriteAllowedUsages) != allowedUsage) {
|
(mAllowedUsage & kMapWriteAllowedUsages) != mAllowedUsage) {
|
||||||
HandleError("Only TransferSrc is allowed with MapWrite");
|
HandleError("Only TransferSrc is allowed with MapWrite");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const nxt::BufferUsageBit kMapReadAllowedUsages = nxt::BufferUsageBit::MapRead | nxt::BufferUsageBit::TransferDst;
|
const nxt::BufferUsageBit kMapReadAllowedUsages = nxt::BufferUsageBit::MapRead | nxt::BufferUsageBit::TransferDst;
|
||||||
if (allowedUsage & nxt::BufferUsageBit::MapRead &&
|
if (mAllowedUsage & nxt::BufferUsageBit::MapRead &&
|
||||||
(allowedUsage & kMapReadAllowedUsages) != allowedUsage) {
|
(mAllowedUsage & kMapReadAllowedUsages) != mAllowedUsage) {
|
||||||
HandleError("Only TransferDst is allowed with MapRead");
|
HandleError("Only TransferDst is allowed with MapRead");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!BufferBase::IsUsagePossible(allowedUsage, currentUsage)) {
|
if (!BufferBase::IsUsagePossible(mAllowedUsage, mCurrentUsage)) {
|
||||||
HandleError("Initial buffer usage is not allowed");
|
HandleError("Initial buffer usage is not allowed");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return device->CreateBuffer(this);
|
return mDevice->CreateBuffer(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BufferBuilder::SetAllowedUsage(nxt::BufferUsageBit usage) {
|
void BufferBuilder::SetAllowedUsage(nxt::BufferUsageBit usage) {
|
||||||
if ((propertiesSet & BUFFER_PROPERTY_ALLOWED_USAGE) != 0) {
|
if ((mPropertiesSet & BUFFER_PROPERTY_ALLOWED_USAGE) != 0) {
|
||||||
HandleError("Buffer allowedUsage property set multiple times");
|
HandleError("Buffer allowedUsage property set multiple times");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->allowedUsage = usage;
|
mAllowedUsage = usage;
|
||||||
propertiesSet |= BUFFER_PROPERTY_ALLOWED_USAGE;
|
mPropertiesSet |= BUFFER_PROPERTY_ALLOWED_USAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BufferBuilder::SetInitialUsage(nxt::BufferUsageBit usage) {
|
void BufferBuilder::SetInitialUsage(nxt::BufferUsageBit usage) {
|
||||||
if ((propertiesSet & BUFFER_PROPERTY_INITIAL_USAGE) != 0) {
|
if ((mPropertiesSet & BUFFER_PROPERTY_INITIAL_USAGE) != 0) {
|
||||||
HandleError("Buffer initialUsage property set multiple times");
|
HandleError("Buffer initialUsage property set multiple times");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->currentUsage = usage;
|
mCurrentUsage = usage;
|
||||||
propertiesSet |= BUFFER_PROPERTY_INITIAL_USAGE;
|
mPropertiesSet |= BUFFER_PROPERTY_INITIAL_USAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BufferBuilder::SetSize(uint32_t size) {
|
void BufferBuilder::SetSize(uint32_t size) {
|
||||||
if ((propertiesSet & BUFFER_PROPERTY_SIZE) != 0) {
|
if ((mPropertiesSet & BUFFER_PROPERTY_SIZE) != 0) {
|
||||||
HandleError("Buffer size property set multiple times");
|
HandleError("Buffer size property set multiple times");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->size = size;
|
mSize = size;
|
||||||
propertiesSet |= BUFFER_PROPERTY_SIZE;
|
mPropertiesSet |= BUFFER_PROPERTY_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// BufferViewBase
|
// BufferViewBase
|
||||||
|
|
||||||
BufferViewBase::BufferViewBase(BufferViewBuilder* builder)
|
BufferViewBase::BufferViewBase(BufferViewBuilder* builder)
|
||||||
: buffer(std::move(builder->buffer)), size(builder->size), offset(builder->offset) {
|
: mBuffer(std::move(builder->mBuffer)), mSize(builder->mSize), mOffset(builder->mOffset) {
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferBase* BufferViewBase::GetBuffer() {
|
BufferBase* BufferViewBase::GetBuffer() {
|
||||||
return buffer.Get();
|
return mBuffer.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t BufferViewBase::GetSize() const {
|
uint32_t BufferViewBase::GetSize() const {
|
||||||
return size;
|
return mSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t BufferViewBase::GetOffset() const {
|
uint32_t BufferViewBase::GetOffset() const {
|
||||||
return offset;
|
return mOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
// BufferViewBuilder
|
// BufferViewBuilder
|
||||||
|
@ -266,34 +266,34 @@ namespace backend {
|
||||||
};
|
};
|
||||||
|
|
||||||
BufferViewBuilder::BufferViewBuilder(DeviceBase* device, BufferBase* buffer)
|
BufferViewBuilder::BufferViewBuilder(DeviceBase* device, BufferBase* buffer)
|
||||||
: Builder(device), buffer(buffer) {
|
: Builder(device), mBuffer(buffer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferViewBase* BufferViewBuilder::GetResultImpl() {
|
BufferViewBase* BufferViewBuilder::GetResultImpl() {
|
||||||
constexpr int allProperties = BUFFER_VIEW_PROPERTY_EXTENT;
|
constexpr int allProperties = BUFFER_VIEW_PROPERTY_EXTENT;
|
||||||
if ((propertiesSet & allProperties) != allProperties) {
|
if ((mPropertiesSet & allProperties) != allProperties) {
|
||||||
HandleError("Buffer view missing properties");
|
HandleError("Buffer view missing properties");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return device->CreateBufferView(this);
|
return mDevice->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 ((mPropertiesSet & BUFFER_VIEW_PROPERTY_EXTENT) != 0) {
|
||||||
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>(mBuffer->GetSize())) {
|
||||||
HandleError("Buffer view end is OOB");
|
HandleError("Buffer view end is OOB");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->offset = offset;
|
mOffset = offset;
|
||||||
this->size = size;
|
mSize = size;
|
||||||
propertiesSet |= BUFFER_VIEW_PROPERTY_EXTENT;
|
mPropertiesSet |= BUFFER_VIEW_PROPERTY_EXTENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,17 +56,17 @@ namespace backend {
|
||||||
virtual void UnmapImpl() = 0;
|
virtual void UnmapImpl() = 0;
|
||||||
virtual void TransitionUsageImpl(nxt::BufferUsageBit currentUsage, nxt::BufferUsageBit targetUsage) = 0;
|
virtual void TransitionUsageImpl(nxt::BufferUsageBit currentUsage, nxt::BufferUsageBit targetUsage) = 0;
|
||||||
|
|
||||||
DeviceBase* device;
|
DeviceBase* mDevice;
|
||||||
uint32_t size;
|
uint32_t mSize;
|
||||||
nxt::BufferUsageBit allowedUsage = nxt::BufferUsageBit::None;
|
nxt::BufferUsageBit mAllowedUsage = nxt::BufferUsageBit::None;
|
||||||
nxt::BufferUsageBit currentUsage = nxt::BufferUsageBit::None;
|
nxt::BufferUsageBit mCurrentUsage = nxt::BufferUsageBit::None;
|
||||||
|
|
||||||
nxtBufferMapReadCallback mapReadCallback = nullptr;
|
nxtBufferMapReadCallback mMapReadCallback = nullptr;
|
||||||
nxtCallbackUserdata mapReadUserdata = 0;
|
nxtCallbackUserdata mMapReadUserdata = 0;
|
||||||
uint32_t mapReadSerial = 0;
|
uint32_t mMapReadSerial = 0;
|
||||||
|
|
||||||
bool frozen = false;
|
bool mIsFrozen = false;
|
||||||
bool mapped = false;
|
bool mIsMapped = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class BufferBuilder : public Builder<BufferBase> {
|
class BufferBuilder : public Builder<BufferBase> {
|
||||||
|
@ -83,10 +83,10 @@ namespace backend {
|
||||||
|
|
||||||
BufferBase* GetResultImpl() override;
|
BufferBase* GetResultImpl() override;
|
||||||
|
|
||||||
uint32_t size;
|
uint32_t mSize;
|
||||||
nxt::BufferUsageBit allowedUsage = nxt::BufferUsageBit::None;
|
nxt::BufferUsageBit mAllowedUsage = nxt::BufferUsageBit::None;
|
||||||
nxt::BufferUsageBit currentUsage = nxt::BufferUsageBit::None;
|
nxt::BufferUsageBit mCurrentUsage = nxt::BufferUsageBit::None;
|
||||||
int propertiesSet = 0;
|
int mPropertiesSet = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class BufferViewBase : public RefCounted {
|
class BufferViewBase : public RefCounted {
|
||||||
|
@ -98,9 +98,9 @@ namespace backend {
|
||||||
uint32_t GetOffset() const;
|
uint32_t GetOffset() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ref<BufferBase> buffer;
|
Ref<BufferBase> mBuffer;
|
||||||
uint32_t size;
|
uint32_t mSize;
|
||||||
uint32_t offset;
|
uint32_t mOffset;
|
||||||
};
|
};
|
||||||
|
|
||||||
class BufferViewBuilder : public Builder<BufferViewBase> {
|
class BufferViewBuilder : public Builder<BufferViewBase> {
|
||||||
|
@ -115,10 +115,10 @@ namespace backend {
|
||||||
|
|
||||||
BufferViewBase* GetResultImpl() override;
|
BufferViewBase* GetResultImpl() override;
|
||||||
|
|
||||||
Ref<BufferBase> buffer;
|
Ref<BufferBase> mBuffer;
|
||||||
uint32_t offset = 0;
|
uint32_t mOffset = 0;
|
||||||
uint32_t size = 0;
|
uint32_t mSize = 0;
|
||||||
int propertiesSet = 0;
|
int mPropertiesSet = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,11 +20,11 @@
|
||||||
namespace backend {
|
namespace backend {
|
||||||
|
|
||||||
bool BuilderBase::CanBeUsed() const {
|
bool BuilderBase::CanBeUsed() const {
|
||||||
return !consumed && !gotStatus;
|
return !mIsConsumed && !mGotStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
DeviceBase* BuilderBase::GetDevice() {
|
DeviceBase* BuilderBase::GetDevice() {
|
||||||
return device;
|
return mDevice;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BuilderBase::HandleError(const char* message) {
|
void BuilderBase::HandleError(const char* message) {
|
||||||
|
@ -34,41 +34,41 @@ namespace backend {
|
||||||
void BuilderBase::SetErrorCallback(nxt::BuilderErrorCallback callback,
|
void BuilderBase::SetErrorCallback(nxt::BuilderErrorCallback callback,
|
||||||
nxt::CallbackUserdata userdata1,
|
nxt::CallbackUserdata userdata1,
|
||||||
nxt::CallbackUserdata userdata2) {
|
nxt::CallbackUserdata userdata2) {
|
||||||
this->callback = callback;
|
mCallback = callback;
|
||||||
this->userdata1 = userdata1;
|
mUserdata1 = userdata1;
|
||||||
this->userdata2 = userdata2;
|
mUserdata2 = userdata2;
|
||||||
}
|
}
|
||||||
|
|
||||||
BuilderBase::BuilderBase(DeviceBase* device) : device(device) {
|
BuilderBase::BuilderBase(DeviceBase* device) : mDevice(device) {
|
||||||
}
|
}
|
||||||
|
|
||||||
BuilderBase::~BuilderBase() {
|
BuilderBase::~BuilderBase() {
|
||||||
if (!consumed && callback != nullptr) {
|
if (!mIsConsumed && mCallback != nullptr) {
|
||||||
callback(NXT_BUILDER_ERROR_STATUS_UNKNOWN, "Builder destroyed before GetResult", userdata1, userdata2);
|
mCallback(NXT_BUILDER_ERROR_STATUS_UNKNOWN, "Builder destroyed before GetResult", mUserdata1, mUserdata2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BuilderBase::SetStatus(nxt::BuilderErrorStatus status, const char* message) {
|
void BuilderBase::SetStatus(nxt::BuilderErrorStatus status, const char* message) {
|
||||||
ASSERT(status != nxt::BuilderErrorStatus::Success);
|
ASSERT(status != nxt::BuilderErrorStatus::Success);
|
||||||
ASSERT(status != nxt::BuilderErrorStatus::Unknown);
|
ASSERT(status != nxt::BuilderErrorStatus::Unknown);
|
||||||
ASSERT(!gotStatus); // This is not strictly necessary but something to strive for.
|
ASSERT(!mGotStatus); // This is not strictly necessary but something to strive for.
|
||||||
gotStatus = true;
|
mGotStatus = true;
|
||||||
|
|
||||||
storedStatus = status;
|
mStoredStatus = status;
|
||||||
storedMessage = message;
|
mStoredMessage = message;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BuilderBase::HandleResult(RefCounted* result) {
|
bool BuilderBase::HandleResult(RefCounted* result) {
|
||||||
// GetResult can only be called once.
|
// GetResult can only be called once.
|
||||||
ASSERT(!consumed);
|
ASSERT(!mIsConsumed);
|
||||||
consumed = true;
|
mIsConsumed = true;
|
||||||
|
|
||||||
// result == nullptr implies there was an error which implies we should have a status set.
|
// result == nullptr implies there was an error which implies we should have a status set.
|
||||||
ASSERT(result != nullptr || gotStatus);
|
ASSERT(result != nullptr || mGotStatus);
|
||||||
|
|
||||||
// If we have any error, then we have to return nullptr
|
// If we have any error, then we have to return nullptr
|
||||||
if (gotStatus) {
|
if (mGotStatus) {
|
||||||
ASSERT(storedStatus != nxt::BuilderErrorStatus::Success);
|
ASSERT(mStoredStatus != nxt::BuilderErrorStatus::Success);
|
||||||
|
|
||||||
// The application will never see "result" so we need to remove the
|
// The application will never see "result" so we need to remove the
|
||||||
// external ref here.
|
// external ref here.
|
||||||
|
@ -78,14 +78,14 @@ namespace backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unhandled builder errors are promoted to device errors
|
// Unhandled builder errors are promoted to device errors
|
||||||
if (!callback) device->HandleError(("Unhandled builder error: " + storedMessage).c_str());
|
if (!mCallback) mDevice->HandleError(("Unhandled builder error: " + mStoredMessage).c_str());
|
||||||
} else {
|
} else {
|
||||||
ASSERT(storedStatus == nxt::BuilderErrorStatus::Success);
|
ASSERT(mStoredStatus == nxt::BuilderErrorStatus::Success);
|
||||||
ASSERT(storedMessage.empty());
|
ASSERT(mStoredMessage.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (callback) {
|
if (mCallback != nullptr) {
|
||||||
callback(static_cast<nxtBuilderErrorStatus>(storedStatus), storedMessage.c_str(), userdata1, userdata2);
|
mCallback(static_cast<nxtBuilderErrorStatus>(mStoredStatus), mStoredMessage.c_str(), mUserdata1, mUserdata2);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result != nullptr;
|
return result != nullptr;
|
||||||
|
|
|
@ -60,20 +60,20 @@ namespace backend {
|
||||||
BuilderBase(DeviceBase* device);
|
BuilderBase(DeviceBase* device);
|
||||||
~BuilderBase();
|
~BuilderBase();
|
||||||
|
|
||||||
DeviceBase* const device;
|
DeviceBase* const mDevice;
|
||||||
bool gotStatus = false;
|
bool mGotStatus = false;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void SetStatus(nxt::BuilderErrorStatus status, const char* message);
|
void SetStatus(nxt::BuilderErrorStatus status, const char* message);
|
||||||
|
|
||||||
nxt::BuilderErrorCallback callback = nullptr;
|
nxt::BuilderErrorCallback mCallback = nullptr;
|
||||||
nxt::CallbackUserdata userdata1 = 0;
|
nxt::CallbackUserdata mUserdata1 = 0;
|
||||||
nxt::CallbackUserdata userdata2 = 0;
|
nxt::CallbackUserdata mUserdata2 = 0;
|
||||||
|
|
||||||
nxt::BuilderErrorStatus storedStatus = nxt::BuilderErrorStatus::Success;
|
nxt::BuilderErrorStatus mStoredStatus = nxt::BuilderErrorStatus::Success;
|
||||||
std::string storedMessage;
|
std::string mStoredMessage;
|
||||||
|
|
||||||
bool consumed = false;
|
bool mIsConsumed = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
// This builder base class is used to capture the calls to GetResult and make sure
|
// This builder base class is used to capture the calls to GetResult and make sure
|
||||||
|
|
|
@ -29,24 +29,24 @@ namespace backend {
|
||||||
// TODO(cwallez@chromium.org): figure out a way to have more type safety for the iterator
|
// TODO(cwallez@chromium.org): figure out a way to have more type safety for the iterator
|
||||||
|
|
||||||
CommandIterator::CommandIterator()
|
CommandIterator::CommandIterator()
|
||||||
: endOfBlock(EndOfBlock) {
|
: mEndOfBlock(EndOfBlock) {
|
||||||
Reset();
|
Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandIterator::~CommandIterator() {
|
CommandIterator::~CommandIterator() {
|
||||||
ASSERT(dataWasDestroyed);
|
ASSERT(mDataWasDestroyed);
|
||||||
|
|
||||||
if (!IsEmpty()) {
|
if (!IsEmpty()) {
|
||||||
for (auto& block : blocks) {
|
for (auto& block : mBlocks) {
|
||||||
free(block.block);
|
free(block.block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandIterator::CommandIterator(CommandIterator&& other)
|
CommandIterator::CommandIterator(CommandIterator&& other)
|
||||||
: endOfBlock(EndOfBlock) {
|
: mEndOfBlock(EndOfBlock) {
|
||||||
if (!other.IsEmpty()) {
|
if (!other.IsEmpty()) {
|
||||||
blocks = std::move(other.blocks);
|
mBlocks = std::move(other.mBlocks);
|
||||||
other.Reset();
|
other.Reset();
|
||||||
}
|
}
|
||||||
other.DataWasDestroyed();
|
other.DataWasDestroyed();
|
||||||
|
@ -55,10 +55,10 @@ namespace backend {
|
||||||
|
|
||||||
CommandIterator& CommandIterator::operator=(CommandIterator&& other) {
|
CommandIterator& CommandIterator::operator=(CommandIterator&& other) {
|
||||||
if (!other.IsEmpty()) {
|
if (!other.IsEmpty()) {
|
||||||
blocks = std::move(other.blocks);
|
mBlocks = std::move(other.mBlocks);
|
||||||
other.Reset();
|
other.Reset();
|
||||||
} else {
|
} else {
|
||||||
blocks.clear();
|
mBlocks.clear();
|
||||||
}
|
}
|
||||||
other.DataWasDestroyed();
|
other.DataWasDestroyed();
|
||||||
Reset();
|
Reset();
|
||||||
|
@ -66,67 +66,67 @@ namespace backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandIterator::CommandIterator(CommandAllocator&& allocator)
|
CommandIterator::CommandIterator(CommandAllocator&& allocator)
|
||||||
: blocks(allocator.AcquireBlocks()), endOfBlock(EndOfBlock) {
|
: mBlocks(allocator.AcquireBlocks()), mEndOfBlock(EndOfBlock) {
|
||||||
Reset();
|
Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandIterator& CommandIterator::operator=(CommandAllocator&& allocator) {
|
CommandIterator& CommandIterator::operator=(CommandAllocator&& allocator) {
|
||||||
blocks = allocator.AcquireBlocks();
|
mBlocks = allocator.AcquireBlocks();
|
||||||
Reset();
|
Reset();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandIterator::Reset() {
|
void CommandIterator::Reset() {
|
||||||
currentBlock = 0;
|
mCurrentBlock = 0;
|
||||||
|
|
||||||
if (blocks.empty()) {
|
if (mBlocks.empty()) {
|
||||||
// This will case the first NextCommandId call to try to move to the next
|
// This will case the first NextCommandId call to try to move to the next
|
||||||
// block and stop the iteration immediately, without special casing the
|
// block and stop the iteration immediately, without special casing the
|
||||||
// initialization.
|
// initialization.
|
||||||
currentPtr = reinterpret_cast<uint8_t*>(&endOfBlock);
|
mCurrentPtr = reinterpret_cast<uint8_t*>(&mEndOfBlock);
|
||||||
blocks.emplace_back();
|
mBlocks.emplace_back();
|
||||||
blocks[0].size = sizeof(endOfBlock);
|
mBlocks[0].size = sizeof(mEndOfBlock);
|
||||||
blocks[0].block = currentPtr;
|
mBlocks[0].block = mCurrentPtr;
|
||||||
} else {
|
} else {
|
||||||
currentPtr = AlignPtr(blocks[0].block, alignof(uint32_t));
|
mCurrentPtr = AlignPtr(mBlocks[0].block, alignof(uint32_t));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandIterator::DataWasDestroyed() {
|
void CommandIterator::DataWasDestroyed() {
|
||||||
dataWasDestroyed = true;
|
mDataWasDestroyed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandIterator::IsEmpty() const {
|
bool CommandIterator::IsEmpty() const {
|
||||||
return blocks[0].block == reinterpret_cast<const uint8_t*>(&endOfBlock);
|
return mBlocks[0].block == reinterpret_cast<const uint8_t*>(&mEndOfBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandIterator::NextCommandId(uint32_t* commandId) {
|
bool CommandIterator::NextCommandId(uint32_t* commandId) {
|
||||||
uint8_t* idPtr = AlignPtr(currentPtr, alignof(uint32_t));
|
uint8_t* idPtr = AlignPtr(mCurrentPtr, alignof(uint32_t));
|
||||||
ASSERT(idPtr + sizeof(uint32_t) <= blocks[currentBlock].block + blocks[currentBlock].size);
|
ASSERT(idPtr + sizeof(uint32_t) <= mBlocks[mCurrentBlock].block + mBlocks[mCurrentBlock].size);
|
||||||
|
|
||||||
uint32_t id = *reinterpret_cast<uint32_t*>(idPtr);
|
uint32_t id = *reinterpret_cast<uint32_t*>(idPtr);
|
||||||
|
|
||||||
if (id == EndOfBlock) {
|
if (id == EndOfBlock) {
|
||||||
currentBlock++;
|
mCurrentBlock++;
|
||||||
if (currentBlock >= blocks.size()) {
|
if (mCurrentBlock >= mBlocks.size()) {
|
||||||
Reset();
|
Reset();
|
||||||
*commandId = EndOfBlock;
|
*commandId = EndOfBlock;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
currentPtr = AlignPtr(blocks[currentBlock].block, alignof(uint32_t));
|
mCurrentPtr = AlignPtr(mBlocks[mCurrentBlock].block, alignof(uint32_t));
|
||||||
return NextCommandId(commandId);
|
return NextCommandId(commandId);
|
||||||
}
|
}
|
||||||
|
|
||||||
currentPtr = idPtr + sizeof(uint32_t);
|
mCurrentPtr = idPtr + sizeof(uint32_t);
|
||||||
*commandId = id;
|
*commandId = id;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* CommandIterator::NextCommand(size_t commandSize, size_t commandAlignment) {
|
void* CommandIterator::NextCommand(size_t commandSize, size_t commandAlignment) {
|
||||||
uint8_t* commandPtr = AlignPtr(currentPtr, commandAlignment);
|
uint8_t* commandPtr = AlignPtr(mCurrentPtr, commandAlignment);
|
||||||
ASSERT(commandPtr + sizeof(commandSize) <= blocks[currentBlock].block + blocks[currentBlock].size);
|
ASSERT(commandPtr + sizeof(commandSize) <= mBlocks[mCurrentBlock].block + mBlocks[mCurrentBlock].size);
|
||||||
|
|
||||||
currentPtr = commandPtr + commandSize;
|
mCurrentPtr = commandPtr + commandSize;
|
||||||
return commandPtr;
|
return commandPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,40 +146,40 @@ namespace backend {
|
||||||
// - Better block allocation, maybe have NXT API to say command buffer is going to have size close to another
|
// - Better block allocation, maybe have NXT API to say command buffer is going to have size close to another
|
||||||
|
|
||||||
CommandAllocator::CommandAllocator()
|
CommandAllocator::CommandAllocator()
|
||||||
: currentPtr(reinterpret_cast<uint8_t*>(&dummyEnum[0])), endPtr(reinterpret_cast<uint8_t*>(&dummyEnum[1])) {
|
: mCurrentPtr(reinterpret_cast<uint8_t*>(&mDummyEnum[0])), mEndPtr(reinterpret_cast<uint8_t*>(&mDummyEnum[1])) {
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandAllocator::~CommandAllocator() {
|
CommandAllocator::~CommandAllocator() {
|
||||||
ASSERT(blocks.empty());
|
ASSERT(mBlocks.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandBlocks&& CommandAllocator::AcquireBlocks() {
|
CommandBlocks&& CommandAllocator::AcquireBlocks() {
|
||||||
ASSERT(currentPtr != nullptr && endPtr != nullptr);
|
ASSERT(mCurrentPtr != nullptr && mEndPtr != nullptr);
|
||||||
ASSERT(IsPtrAligned(currentPtr, alignof(uint32_t)));
|
ASSERT(IsPtrAligned(mCurrentPtr, alignof(uint32_t)));
|
||||||
ASSERT(currentPtr + sizeof(uint32_t) <= endPtr);
|
ASSERT(mCurrentPtr + sizeof(uint32_t) <= mEndPtr);
|
||||||
*reinterpret_cast<uint32_t*>(currentPtr) = EndOfBlock;
|
*reinterpret_cast<uint32_t*>(mCurrentPtr) = EndOfBlock;
|
||||||
|
|
||||||
currentPtr = nullptr;
|
mCurrentPtr = nullptr;
|
||||||
endPtr = nullptr;
|
mEndPtr = nullptr;
|
||||||
return std::move(blocks);
|
return std::move(mBlocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* CommandAllocator::Allocate(uint32_t commandId, size_t commandSize, size_t commandAlignment) {
|
uint8_t* CommandAllocator::Allocate(uint32_t commandId, size_t commandSize, size_t commandAlignment) {
|
||||||
ASSERT(currentPtr != nullptr);
|
ASSERT(mCurrentPtr != nullptr);
|
||||||
ASSERT(endPtr != nullptr);
|
ASSERT(mEndPtr != nullptr);
|
||||||
ASSERT(commandId != EndOfBlock);
|
ASSERT(commandId != EndOfBlock);
|
||||||
|
|
||||||
// It should always be possible to allocate one id, for EndOfBlock tagging,
|
// It should always be possible to allocate one id, for EndOfBlock tagging,
|
||||||
ASSERT(IsPtrAligned(currentPtr, alignof(uint32_t)));
|
ASSERT(IsPtrAligned(mCurrentPtr, alignof(uint32_t)));
|
||||||
ASSERT(currentPtr + sizeof(uint32_t) <= endPtr);
|
ASSERT(mCurrentPtr + sizeof(uint32_t) <= mEndPtr);
|
||||||
uint32_t* idAlloc = reinterpret_cast<uint32_t*>(currentPtr);
|
uint32_t* idAlloc = reinterpret_cast<uint32_t*>(mCurrentPtr);
|
||||||
|
|
||||||
uint8_t* commandAlloc = AlignPtr(currentPtr + sizeof(uint32_t), commandAlignment);
|
uint8_t* commandAlloc = AlignPtr(mCurrentPtr + sizeof(uint32_t), commandAlignment);
|
||||||
uint8_t* nextPtr = AlignPtr(commandAlloc + commandSize, alignof(uint32_t));
|
uint8_t* nextPtr = AlignPtr(commandAlloc + commandSize, alignof(uint32_t));
|
||||||
|
|
||||||
// When there is not enough space, we signal the EndOfBlock, so that the iterator nows to
|
// When there is not enough space, we signal the EndOfBlock, so that the iterator nows to
|
||||||
// move to the next one. EndOfBlock on the last block means the end of the commands.
|
// move to the next one. EndOfBlock on the last block means the end of the commands.
|
||||||
if (nextPtr + sizeof(uint32_t) > endPtr) {
|
if (nextPtr + sizeof(uint32_t) > mEndPtr) {
|
||||||
|
|
||||||
// Even if we are not able to get another block, the list of commands will be well-formed
|
// Even if we are not able to get another block, the list of commands will be well-formed
|
||||||
// and iterable as this block will be that last one.
|
// and iterable as this block will be that last one.
|
||||||
|
@ -187,15 +187,15 @@ namespace backend {
|
||||||
|
|
||||||
// Make sure we have space for current allocation, plus end of block and alignment padding
|
// Make sure we have space for current allocation, plus end of block and alignment padding
|
||||||
// for the first id.
|
// for the first id.
|
||||||
ASSERT(nextPtr > currentPtr);
|
ASSERT(nextPtr > mCurrentPtr);
|
||||||
if (!GetNewBlock(static_cast<size_t>(nextPtr - currentPtr) + sizeof(uint32_t) + alignof(uint32_t))) {
|
if (!GetNewBlock(static_cast<size_t>(nextPtr - mCurrentPtr) + sizeof(uint32_t) + alignof(uint32_t))) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return Allocate(commandId, commandSize, commandAlignment);
|
return Allocate(commandId, commandSize, commandAlignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
*idAlloc = commandId;
|
*idAlloc = commandId;
|
||||||
currentPtr = nextPtr;
|
mCurrentPtr = nextPtr;
|
||||||
return commandAlloc;
|
return commandAlloc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,16 +205,16 @@ namespace backend {
|
||||||
|
|
||||||
bool CommandAllocator::GetNewBlock(size_t minimumSize) {
|
bool CommandAllocator::GetNewBlock(size_t minimumSize) {
|
||||||
// Allocate blocks doubling sizes each time, to a maximum of 16k (or at least minimumSize).
|
// Allocate blocks doubling sizes each time, to a maximum of 16k (or at least minimumSize).
|
||||||
lastAllocationSize = std::max(minimumSize, std::min(lastAllocationSize * 2, size_t(16384)));
|
mLastAllocationSize = std::max(minimumSize, std::min(mLastAllocationSize * 2, size_t(16384)));
|
||||||
|
|
||||||
uint8_t* block = reinterpret_cast<uint8_t*>(malloc(lastAllocationSize));
|
uint8_t* block = reinterpret_cast<uint8_t*>(malloc(mLastAllocationSize));
|
||||||
if (block == nullptr) {
|
if (block == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
blocks.push_back({lastAllocationSize, block});
|
mBlocks.push_back({mLastAllocationSize, block});
|
||||||
currentPtr = AlignPtr(block, alignof(uint32_t));
|
mCurrentPtr = AlignPtr(block, alignof(uint32_t));
|
||||||
endPtr = block + lastAllocationSize;
|
mEndPtr = block + mLastAllocationSize;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -96,12 +96,12 @@ namespace backend {
|
||||||
void* NextCommand(size_t commandSize, size_t commandAlignment);
|
void* NextCommand(size_t commandSize, size_t commandAlignment);
|
||||||
void* NextData(size_t dataSize, size_t dataAlignment);
|
void* NextData(size_t dataSize, size_t dataAlignment);
|
||||||
|
|
||||||
CommandBlocks blocks;
|
CommandBlocks mBlocks;
|
||||||
uint8_t* currentPtr = nullptr;
|
uint8_t* mCurrentPtr = nullptr;
|
||||||
size_t currentBlock = 0;
|
size_t mCurrentBlock = 0;
|
||||||
// Used to avoid a special case for empty iterators.
|
// Used to avoid a special case for empty iterators.
|
||||||
uint32_t endOfBlock;
|
uint32_t mEndOfBlock;
|
||||||
bool dataWasDestroyed = false;
|
bool mDataWasDestroyed = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CommandAllocator {
|
class CommandAllocator {
|
||||||
|
@ -129,20 +129,20 @@ namespace backend {
|
||||||
uint8_t* AllocateData(size_t dataSize, size_t dataAlignment);
|
uint8_t* AllocateData(size_t dataSize, size_t dataAlignment);
|
||||||
bool GetNewBlock(size_t minimumSize);
|
bool GetNewBlock(size_t minimumSize);
|
||||||
|
|
||||||
CommandBlocks blocks;
|
CommandBlocks mBlocks;
|
||||||
size_t lastAllocationSize = 2048;
|
size_t mLastAllocationSize = 2048;
|
||||||
|
|
||||||
// Pointers to the current range of allocation in the block. Guaranteed to allow
|
// Pointers to the current range of allocation in the block. Guaranteed to allow
|
||||||
// for at least one uint32_t is not nullptr, so that the special EndOfBlock command id
|
// for at least one uint32_t is not nullptr, so that the special EndOfBlock command id
|
||||||
// can always be written.
|
// can always be written.
|
||||||
// Nullptr iff the blocks were moved out.
|
// Nullptr iff the blocks were moved out.
|
||||||
uint8_t* currentPtr = nullptr;
|
uint8_t* mCurrentPtr = nullptr;
|
||||||
uint8_t* endPtr = nullptr;
|
uint8_t* mEndPtr = nullptr;
|
||||||
|
|
||||||
// Data used for the block range at initialization so that the first call to Allocate
|
// Data used for the block range at initialization so that the first call to Allocate
|
||||||
// sees there is not enough space and calls GetNewBlock. This avoids having to special
|
// sees there is not enough space and calls GetNewBlock. This avoids having to special
|
||||||
// case the initialization in Allocate.
|
// case the initialization in Allocate.
|
||||||
uint32_t dummyEnum[1] = {0};
|
uint32_t mDummyEnum[1] = {0};
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,21 +110,21 @@ namespace backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandBufferBase::CommandBufferBase(CommandBufferBuilder* builder)
|
CommandBufferBase::CommandBufferBase(CommandBufferBuilder* builder)
|
||||||
: device(builder->device),
|
: mDevice(builder->mDevice),
|
||||||
buffersTransitioned(std::move(builder->state->buffersTransitioned)),
|
mBuffersTransitioned(std::move(builder->mState->mBuffersTransitioned)),
|
||||||
texturesTransitioned(std::move(builder->state->texturesTransitioned)) {
|
mTexturesTransitioned(std::move(builder->mState->mTexturesTransitioned)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandBufferBase::ValidateResourceUsagesImmediate() {
|
bool CommandBufferBase::ValidateResourceUsagesImmediate() {
|
||||||
for (auto buffer : buffersTransitioned) {
|
for (auto buffer : mBuffersTransitioned) {
|
||||||
if (buffer->IsFrozen()) {
|
if (buffer->IsFrozen()) {
|
||||||
device->HandleError("Command buffer: cannot transition buffer with frozen usage");
|
mDevice->HandleError("Command buffer: cannot transition buffer with frozen usage");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (auto texture : texturesTransitioned) {
|
for (auto texture : mTexturesTransitioned) {
|
||||||
if (texture->IsFrozen()) {
|
if (texture->IsFrozen()) {
|
||||||
device->HandleError("Command buffer: cannot transition texture with frozen usage");
|
mDevice->HandleError("Command buffer: cannot transition texture with frozen usage");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -132,7 +132,7 @@ namespace backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
DeviceBase* CommandBufferBase::GetDevice() {
|
DeviceBase* CommandBufferBase::GetDevice() {
|
||||||
return device;
|
return mDevice;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FreeCommands(CommandIterator* commands) {
|
void FreeCommands(CommandIterator* commands) {
|
||||||
|
@ -381,13 +381,13 @@ namespace backend {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandBufferBuilder::CommandBufferBuilder(DeviceBase* device) : Builder(device), state(std::make_unique<CommandBufferStateTracker>(this)) {
|
CommandBufferBuilder::CommandBufferBuilder(DeviceBase* device) : Builder(device), mState(std::make_unique<CommandBufferStateTracker>(this)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandBufferBuilder::~CommandBufferBuilder() {
|
CommandBufferBuilder::~CommandBufferBuilder() {
|
||||||
if (!commandsAcquired) {
|
if (!mWereCommandsAcquired) {
|
||||||
MoveToIterator();
|
MoveToIterator();
|
||||||
FreeCommands(&iterator);
|
FreeCommands(&mIterator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -395,12 +395,12 @@ namespace backend {
|
||||||
MoveToIterator();
|
MoveToIterator();
|
||||||
|
|
||||||
Command type;
|
Command type;
|
||||||
while (iterator.NextCommandId(&type)) {
|
while (mIterator.NextCommandId(&type)) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Command::BeginComputePass:
|
case Command::BeginComputePass:
|
||||||
{
|
{
|
||||||
iterator.NextCommand<BeginComputePassCmd>();
|
mIterator.NextCommand<BeginComputePassCmd>();
|
||||||
if (!state->BeginComputePass()) {
|
if (!mState->BeginComputePass()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -408,7 +408,7 @@ namespace backend {
|
||||||
|
|
||||||
case Command::BeginRenderPass:
|
case Command::BeginRenderPass:
|
||||||
{
|
{
|
||||||
BeginRenderPassCmd* cmd = iterator.NextCommand<BeginRenderPassCmd>();
|
BeginRenderPassCmd* cmd = mIterator.NextCommand<BeginRenderPassCmd>();
|
||||||
auto* renderPass = cmd->renderPass.Get();
|
auto* renderPass = cmd->renderPass.Get();
|
||||||
auto* framebuffer = cmd->framebuffer.Get();
|
auto* framebuffer = cmd->framebuffer.Get();
|
||||||
// TODO(kainino@chromium.org): null checks should not be necessary
|
// TODO(kainino@chromium.org): null checks should not be necessary
|
||||||
|
@ -420,7 +420,7 @@ namespace backend {
|
||||||
HandleError("Framebuffer is invalid");
|
HandleError("Framebuffer is invalid");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!state->BeginRenderPass(renderPass, framebuffer)) {
|
if (!mState->BeginRenderPass(renderPass, framebuffer)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -428,8 +428,8 @@ namespace backend {
|
||||||
|
|
||||||
case Command::BeginRenderSubpass:
|
case Command::BeginRenderSubpass:
|
||||||
{
|
{
|
||||||
iterator.NextCommand<BeginRenderSubpassCmd>();
|
mIterator.NextCommand<BeginRenderSubpassCmd>();
|
||||||
if (!state->BeginSubpass()) {
|
if (!mState->BeginSubpass()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -437,12 +437,12 @@ namespace backend {
|
||||||
|
|
||||||
case Command::CopyBufferToBuffer:
|
case Command::CopyBufferToBuffer:
|
||||||
{
|
{
|
||||||
CopyBufferToBufferCmd* copy = iterator.NextCommand<CopyBufferToBufferCmd>();
|
CopyBufferToBufferCmd* copy = mIterator.NextCommand<CopyBufferToBufferCmd>();
|
||||||
if (!ValidateCopySizeFitsInBuffer(this, copy->source, copy->size) ||
|
if (!ValidateCopySizeFitsInBuffer(this, copy->source, copy->size) ||
|
||||||
!ValidateCopySizeFitsInBuffer(this, copy->destination, copy->size) ||
|
!ValidateCopySizeFitsInBuffer(this, copy->destination, copy->size) ||
|
||||||
!state->ValidateCanCopy() ||
|
!mState->ValidateCanCopy() ||
|
||||||
!state->ValidateCanUseBufferAs(copy->source.buffer.Get(), nxt::BufferUsageBit::TransferSrc) ||
|
!mState->ValidateCanUseBufferAs(copy->source.buffer.Get(), nxt::BufferUsageBit::TransferSrc) ||
|
||||||
!state->ValidateCanUseBufferAs(copy->destination.buffer.Get(), nxt::BufferUsageBit::TransferDst)) {
|
!mState->ValidateCanUseBufferAs(copy->destination.buffer.Get(), nxt::BufferUsageBit::TransferDst)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -450,7 +450,7 @@ namespace backend {
|
||||||
|
|
||||||
case Command::CopyBufferToTexture:
|
case Command::CopyBufferToTexture:
|
||||||
{
|
{
|
||||||
CopyBufferToTextureCmd* copy = iterator.NextCommand<CopyBufferToTextureCmd>();
|
CopyBufferToTextureCmd* copy = mIterator.NextCommand<CopyBufferToTextureCmd>();
|
||||||
|
|
||||||
uint32_t bufferCopySize = 0;
|
uint32_t bufferCopySize = 0;
|
||||||
if (!ValidateRowPitch(this, copy->destination, copy->rowPitch) ||
|
if (!ValidateRowPitch(this, copy->destination, copy->rowPitch) ||
|
||||||
|
@ -458,9 +458,9 @@ namespace backend {
|
||||||
!ValidateCopyLocationFitsInTexture(this, copy->destination) ||
|
!ValidateCopyLocationFitsInTexture(this, copy->destination) ||
|
||||||
!ValidateCopySizeFitsInBuffer(this, copy->source, bufferCopySize) ||
|
!ValidateCopySizeFitsInBuffer(this, copy->source, bufferCopySize) ||
|
||||||
!ValidateTexelBufferOffset(this, copy->destination.texture.Get(), copy->source) ||
|
!ValidateTexelBufferOffset(this, copy->destination.texture.Get(), copy->source) ||
|
||||||
!state->ValidateCanCopy() ||
|
!mState->ValidateCanCopy() ||
|
||||||
!state->ValidateCanUseBufferAs(copy->source.buffer.Get(), nxt::BufferUsageBit::TransferSrc) ||
|
!mState->ValidateCanUseBufferAs(copy->source.buffer.Get(), nxt::BufferUsageBit::TransferSrc) ||
|
||||||
!state->ValidateCanUseTextureAs(copy->destination.texture.Get(), nxt::TextureUsageBit::TransferDst)) {
|
!mState->ValidateCanUseTextureAs(copy->destination.texture.Get(), nxt::TextureUsageBit::TransferDst)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -468,7 +468,7 @@ namespace backend {
|
||||||
|
|
||||||
case Command::CopyTextureToBuffer:
|
case Command::CopyTextureToBuffer:
|
||||||
{
|
{
|
||||||
CopyTextureToBufferCmd* copy = iterator.NextCommand<CopyTextureToBufferCmd>();
|
CopyTextureToBufferCmd* copy = mIterator.NextCommand<CopyTextureToBufferCmd>();
|
||||||
|
|
||||||
uint32_t bufferCopySize = 0;
|
uint32_t bufferCopySize = 0;
|
||||||
if (!ValidateRowPitch(this, copy->source, copy->rowPitch) ||
|
if (!ValidateRowPitch(this, copy->source, copy->rowPitch) ||
|
||||||
|
@ -476,9 +476,9 @@ namespace backend {
|
||||||
!ValidateCopyLocationFitsInTexture(this, copy->source) ||
|
!ValidateCopyLocationFitsInTexture(this, copy->source) ||
|
||||||
!ValidateCopySizeFitsInBuffer(this, copy->destination, bufferCopySize) ||
|
!ValidateCopySizeFitsInBuffer(this, copy->destination, bufferCopySize) ||
|
||||||
!ValidateTexelBufferOffset(this, copy->source.texture.Get(), copy->destination) ||
|
!ValidateTexelBufferOffset(this, copy->source.texture.Get(), copy->destination) ||
|
||||||
!state->ValidateCanCopy() ||
|
!mState->ValidateCanCopy() ||
|
||||||
!state->ValidateCanUseTextureAs(copy->source.texture.Get(), nxt::TextureUsageBit::TransferSrc) ||
|
!mState->ValidateCanUseTextureAs(copy->source.texture.Get(), nxt::TextureUsageBit::TransferSrc) ||
|
||||||
!state->ValidateCanUseBufferAs(copy->destination.buffer.Get(), nxt::BufferUsageBit::TransferDst)) {
|
!mState->ValidateCanUseBufferAs(copy->destination.buffer.Get(), nxt::BufferUsageBit::TransferDst)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -486,8 +486,8 @@ namespace backend {
|
||||||
|
|
||||||
case Command::Dispatch:
|
case Command::Dispatch:
|
||||||
{
|
{
|
||||||
iterator.NextCommand<DispatchCmd>();
|
mIterator.NextCommand<DispatchCmd>();
|
||||||
if (!state->ValidateCanDispatch()) {
|
if (!mState->ValidateCanDispatch()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -495,8 +495,8 @@ namespace backend {
|
||||||
|
|
||||||
case Command::DrawArrays:
|
case Command::DrawArrays:
|
||||||
{
|
{
|
||||||
iterator.NextCommand<DrawArraysCmd>();
|
mIterator.NextCommand<DrawArraysCmd>();
|
||||||
if (!state->ValidateCanDrawArrays()) {
|
if (!mState->ValidateCanDrawArrays()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -504,8 +504,8 @@ namespace backend {
|
||||||
|
|
||||||
case Command::DrawElements:
|
case Command::DrawElements:
|
||||||
{
|
{
|
||||||
iterator.NextCommand<DrawElementsCmd>();
|
mIterator.NextCommand<DrawElementsCmd>();
|
||||||
if (!state->ValidateCanDrawElements()) {
|
if (!mState->ValidateCanDrawElements()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -513,8 +513,8 @@ namespace backend {
|
||||||
|
|
||||||
case Command::EndComputePass:
|
case Command::EndComputePass:
|
||||||
{
|
{
|
||||||
iterator.NextCommand<EndComputePassCmd>();
|
mIterator.NextCommand<EndComputePassCmd>();
|
||||||
if (!state->EndComputePass()) {
|
if (!mState->EndComputePass()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -522,8 +522,8 @@ namespace backend {
|
||||||
|
|
||||||
case Command::EndRenderPass:
|
case Command::EndRenderPass:
|
||||||
{
|
{
|
||||||
iterator.NextCommand<EndRenderPassCmd>();
|
mIterator.NextCommand<EndRenderPassCmd>();
|
||||||
if (!state->EndRenderPass()) {
|
if (!mState->EndRenderPass()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -531,8 +531,8 @@ namespace backend {
|
||||||
|
|
||||||
case Command::EndRenderSubpass:
|
case Command::EndRenderSubpass:
|
||||||
{
|
{
|
||||||
iterator.NextCommand<EndRenderSubpassCmd>();
|
mIterator.NextCommand<EndRenderSubpassCmd>();
|
||||||
if (!state->EndSubpass()) {
|
if (!mState->EndSubpass()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -540,9 +540,9 @@ namespace backend {
|
||||||
|
|
||||||
case Command::SetComputePipeline:
|
case Command::SetComputePipeline:
|
||||||
{
|
{
|
||||||
SetComputePipelineCmd* cmd = iterator.NextCommand<SetComputePipelineCmd>();
|
SetComputePipelineCmd* cmd = mIterator.NextCommand<SetComputePipelineCmd>();
|
||||||
ComputePipelineBase* pipeline = cmd->pipeline.Get();
|
ComputePipelineBase* pipeline = cmd->pipeline.Get();
|
||||||
if (!state->SetComputePipeline(pipeline)) {
|
if (!mState->SetComputePipeline(pipeline)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -550,9 +550,9 @@ namespace backend {
|
||||||
|
|
||||||
case Command::SetRenderPipeline:
|
case Command::SetRenderPipeline:
|
||||||
{
|
{
|
||||||
SetRenderPipelineCmd* cmd = iterator.NextCommand<SetRenderPipelineCmd>();
|
SetRenderPipelineCmd* cmd = mIterator.NextCommand<SetRenderPipelineCmd>();
|
||||||
RenderPipelineBase* pipeline = cmd->pipeline.Get();
|
RenderPipelineBase* pipeline = cmd->pipeline.Get();
|
||||||
if (!state->SetRenderPipeline(pipeline)) {
|
if (!mState->SetRenderPipeline(pipeline)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -560,11 +560,11 @@ namespace backend {
|
||||||
|
|
||||||
case Command::SetPushConstants:
|
case Command::SetPushConstants:
|
||||||
{
|
{
|
||||||
SetPushConstantsCmd* cmd = iterator.NextCommand<SetPushConstantsCmd>();
|
SetPushConstantsCmd* cmd = mIterator.NextCommand<SetPushConstantsCmd>();
|
||||||
iterator.NextData<uint32_t>(cmd->count);
|
mIterator.NextData<uint32_t>(cmd->count);
|
||||||
// Validation of count and offset has already been done when the command was recorded
|
// Validation of count and offset has already been done when the command was recorded
|
||||||
// because it impacts the size of an allocation in the CommandAllocator.
|
// because it impacts the size of an allocation in the CommandAllocator.
|
||||||
if (!state->ValidateSetPushConstants(cmd->stages)) {
|
if (!mState->ValidateSetPushConstants(cmd->stages)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -572,8 +572,8 @@ namespace backend {
|
||||||
|
|
||||||
case Command::SetStencilReference:
|
case Command::SetStencilReference:
|
||||||
{
|
{
|
||||||
iterator.NextCommand<SetStencilReferenceCmd>();
|
mIterator.NextCommand<SetStencilReferenceCmd>();
|
||||||
if (!state->HaveRenderSubpass()) {
|
if (!mState->HaveRenderSubpass()) {
|
||||||
HandleError("Can't set stencil reference without an active render subpass");
|
HandleError("Can't set stencil reference without an active render subpass");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -582,8 +582,8 @@ namespace backend {
|
||||||
|
|
||||||
case Command::SetBlendColor:
|
case Command::SetBlendColor:
|
||||||
{
|
{
|
||||||
iterator.NextCommand<SetBlendColorCmd>();
|
mIterator.NextCommand<SetBlendColorCmd>();
|
||||||
if (!state->HaveRenderSubpass()) {
|
if (!mState->HaveRenderSubpass()) {
|
||||||
HandleError("Can't set blend color without an active render subpass");
|
HandleError("Can't set blend color without an active render subpass");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -592,8 +592,8 @@ namespace backend {
|
||||||
|
|
||||||
case Command::SetBindGroup:
|
case Command::SetBindGroup:
|
||||||
{
|
{
|
||||||
SetBindGroupCmd* cmd = iterator.NextCommand<SetBindGroupCmd>();
|
SetBindGroupCmd* cmd = mIterator.NextCommand<SetBindGroupCmd>();
|
||||||
if (!state->SetBindGroup(cmd->index, cmd->group.Get())) {
|
if (!mState->SetBindGroup(cmd->index, cmd->group.Get())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -601,8 +601,8 @@ namespace backend {
|
||||||
|
|
||||||
case Command::SetIndexBuffer:
|
case Command::SetIndexBuffer:
|
||||||
{
|
{
|
||||||
SetIndexBufferCmd* cmd = iterator.NextCommand<SetIndexBufferCmd>();
|
SetIndexBufferCmd* cmd = mIterator.NextCommand<SetIndexBufferCmd>();
|
||||||
if (!state->SetIndexBuffer(cmd->buffer.Get())) {
|
if (!mState->SetIndexBuffer(cmd->buffer.Get())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -610,20 +610,20 @@ namespace backend {
|
||||||
|
|
||||||
case Command::SetVertexBuffers:
|
case Command::SetVertexBuffers:
|
||||||
{
|
{
|
||||||
SetVertexBuffersCmd* cmd = iterator.NextCommand<SetVertexBuffersCmd>();
|
SetVertexBuffersCmd* cmd = mIterator.NextCommand<SetVertexBuffersCmd>();
|
||||||
auto buffers = iterator.NextData<Ref<BufferBase>>(cmd->count);
|
auto buffers = mIterator.NextData<Ref<BufferBase>>(cmd->count);
|
||||||
iterator.NextData<uint32_t>(cmd->count);
|
mIterator.NextData<uint32_t>(cmd->count);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < cmd->count; ++i) {
|
for (uint32_t i = 0; i < cmd->count; ++i) {
|
||||||
state->SetVertexBuffer(cmd->startSlot + i, buffers[i].Get());
|
mState->SetVertexBuffer(cmd->startSlot + i, buffers[i].Get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Command::TransitionBufferUsage:
|
case Command::TransitionBufferUsage:
|
||||||
{
|
{
|
||||||
TransitionBufferUsageCmd* cmd = iterator.NextCommand<TransitionBufferUsageCmd>();
|
TransitionBufferUsageCmd* cmd = mIterator.NextCommand<TransitionBufferUsageCmd>();
|
||||||
if (!state->TransitionBufferUsage(cmd->buffer.Get(), cmd->usage)) {
|
if (!mState->TransitionBufferUsage(cmd->buffer.Get(), cmd->usage)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -631,8 +631,8 @@ namespace backend {
|
||||||
|
|
||||||
case Command::TransitionTextureUsage:
|
case Command::TransitionTextureUsage:
|
||||||
{
|
{
|
||||||
TransitionTextureUsageCmd* cmd = iterator.NextCommand<TransitionTextureUsageCmd>();
|
TransitionTextureUsageCmd* cmd = mIterator.NextCommand<TransitionTextureUsageCmd>();
|
||||||
if (!state->TransitionTextureUsage(cmd->texture.Get(), cmd->usage)) {
|
if (!mState->TransitionTextureUsage(cmd->texture.Get(), cmd->usage)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -641,7 +641,7 @@ namespace backend {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!state->ValidateEndCommandBuffer()) {
|
if (!mState->ValidateEndCommandBuffer()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -649,33 +649,33 @@ namespace backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandIterator CommandBufferBuilder::AcquireCommands() {
|
CommandIterator CommandBufferBuilder::AcquireCommands() {
|
||||||
ASSERT(!commandsAcquired);
|
ASSERT(!mWereCommandsAcquired);
|
||||||
commandsAcquired = true;
|
mWereCommandsAcquired = true;
|
||||||
return std::move(iterator);
|
return std::move(mIterator);
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandBufferBase* CommandBufferBuilder::GetResultImpl() {
|
CommandBufferBase* CommandBufferBuilder::GetResultImpl() {
|
||||||
MoveToIterator();
|
MoveToIterator();
|
||||||
return device->CreateCommandBuffer(this);
|
return mDevice->CreateCommandBuffer(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandBufferBuilder::BeginComputePass() {
|
void CommandBufferBuilder::BeginComputePass() {
|
||||||
allocator.Allocate<BeginComputePassCmd>(Command::BeginComputePass);
|
mAllocator.Allocate<BeginComputePassCmd>(Command::BeginComputePass);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandBufferBuilder::BeginRenderPass(RenderPassBase* renderPass, FramebufferBase* framebuffer) {
|
void CommandBufferBuilder::BeginRenderPass(RenderPassBase* renderPass, FramebufferBase* framebuffer) {
|
||||||
BeginRenderPassCmd* cmd = allocator.Allocate<BeginRenderPassCmd>(Command::BeginRenderPass);
|
BeginRenderPassCmd* cmd = mAllocator.Allocate<BeginRenderPassCmd>(Command::BeginRenderPass);
|
||||||
new(cmd) BeginRenderPassCmd;
|
new(cmd) BeginRenderPassCmd;
|
||||||
cmd->renderPass = renderPass;
|
cmd->renderPass = renderPass;
|
||||||
cmd->framebuffer = framebuffer;
|
cmd->framebuffer = framebuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandBufferBuilder::BeginRenderSubpass() {
|
void CommandBufferBuilder::BeginRenderSubpass() {
|
||||||
allocator.Allocate<BeginRenderSubpassCmd>(Command::BeginRenderSubpass);
|
mAllocator.Allocate<BeginRenderSubpassCmd>(Command::BeginRenderSubpass);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandBufferBuilder::CopyBufferToBuffer(BufferBase* source, uint32_t sourceOffset, BufferBase* destination, uint32_t destinationOffset, uint32_t size) {
|
void CommandBufferBuilder::CopyBufferToBuffer(BufferBase* source, uint32_t sourceOffset, BufferBase* destination, uint32_t destinationOffset, uint32_t size) {
|
||||||
CopyBufferToBufferCmd* copy = allocator.Allocate<CopyBufferToBufferCmd>(Command::CopyBufferToBuffer);
|
CopyBufferToBufferCmd* copy = mAllocator.Allocate<CopyBufferToBufferCmd>(Command::CopyBufferToBuffer);
|
||||||
new(copy) CopyBufferToBufferCmd;
|
new(copy) CopyBufferToBufferCmd;
|
||||||
copy->source.buffer = source;
|
copy->source.buffer = source;
|
||||||
copy->source.offset = sourceOffset;
|
copy->source.offset = sourceOffset;
|
||||||
|
@ -690,7 +690,7 @@ namespace backend {
|
||||||
if (rowPitch == 0) {
|
if (rowPitch == 0) {
|
||||||
rowPitch = ComputeDefaultRowPitch(texture, width);
|
rowPitch = ComputeDefaultRowPitch(texture, width);
|
||||||
}
|
}
|
||||||
CopyBufferToTextureCmd* copy = allocator.Allocate<CopyBufferToTextureCmd>(Command::CopyBufferToTexture);
|
CopyBufferToTextureCmd* copy = mAllocator.Allocate<CopyBufferToTextureCmd>(Command::CopyBufferToTexture);
|
||||||
new(copy) CopyBufferToTextureCmd;
|
new(copy) CopyBufferToTextureCmd;
|
||||||
copy->source.buffer = buffer;
|
copy->source.buffer = buffer;
|
||||||
copy->source.offset = bufferOffset;
|
copy->source.offset = bufferOffset;
|
||||||
|
@ -711,7 +711,7 @@ namespace backend {
|
||||||
if (rowPitch == 0) {
|
if (rowPitch == 0) {
|
||||||
rowPitch = ComputeDefaultRowPitch(texture, width);
|
rowPitch = ComputeDefaultRowPitch(texture, width);
|
||||||
}
|
}
|
||||||
CopyTextureToBufferCmd* copy = allocator.Allocate<CopyTextureToBufferCmd>(Command::CopyTextureToBuffer);
|
CopyTextureToBufferCmd* copy = mAllocator.Allocate<CopyTextureToBufferCmd>(Command::CopyTextureToBuffer);
|
||||||
new(copy) CopyTextureToBufferCmd;
|
new(copy) CopyTextureToBufferCmd;
|
||||||
copy->source.texture = texture;
|
copy->source.texture = texture;
|
||||||
copy->source.x = x;
|
copy->source.x = x;
|
||||||
|
@ -727,7 +727,7 @@ namespace backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandBufferBuilder::Dispatch(uint32_t x, uint32_t y, uint32_t z) {
|
void CommandBufferBuilder::Dispatch(uint32_t x, uint32_t y, uint32_t z) {
|
||||||
DispatchCmd* dispatch = allocator.Allocate<DispatchCmd>(Command::Dispatch);
|
DispatchCmd* dispatch = mAllocator.Allocate<DispatchCmd>(Command::Dispatch);
|
||||||
new(dispatch) DispatchCmd;
|
new(dispatch) DispatchCmd;
|
||||||
dispatch->x = x;
|
dispatch->x = x;
|
||||||
dispatch->y = y;
|
dispatch->y = y;
|
||||||
|
@ -735,7 +735,7 @@ namespace backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandBufferBuilder::DrawArrays(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) {
|
void CommandBufferBuilder::DrawArrays(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) {
|
||||||
DrawArraysCmd* draw = allocator.Allocate<DrawArraysCmd>(Command::DrawArrays);
|
DrawArraysCmd* draw = mAllocator.Allocate<DrawArraysCmd>(Command::DrawArrays);
|
||||||
new(draw) DrawArraysCmd;
|
new(draw) DrawArraysCmd;
|
||||||
draw->vertexCount = vertexCount;
|
draw->vertexCount = vertexCount;
|
||||||
draw->instanceCount = instanceCount;
|
draw->instanceCount = instanceCount;
|
||||||
|
@ -744,7 +744,7 @@ namespace backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandBufferBuilder::DrawElements(uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, uint32_t firstInstance) {
|
void CommandBufferBuilder::DrawElements(uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, uint32_t firstInstance) {
|
||||||
DrawElementsCmd* draw = allocator.Allocate<DrawElementsCmd>(Command::DrawElements);
|
DrawElementsCmd* draw = mAllocator.Allocate<DrawElementsCmd>(Command::DrawElements);
|
||||||
new(draw) DrawElementsCmd;
|
new(draw) DrawElementsCmd;
|
||||||
draw->indexCount = indexCount;
|
draw->indexCount = indexCount;
|
||||||
draw->instanceCount = instanceCount;
|
draw->instanceCount = instanceCount;
|
||||||
|
@ -753,25 +753,25 @@ namespace backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandBufferBuilder::EndComputePass() {
|
void CommandBufferBuilder::EndComputePass() {
|
||||||
allocator.Allocate<EndComputePassCmd>(Command::EndComputePass);
|
mAllocator.Allocate<EndComputePassCmd>(Command::EndComputePass);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandBufferBuilder::EndRenderPass() {
|
void CommandBufferBuilder::EndRenderPass() {
|
||||||
allocator.Allocate<EndRenderPassCmd>(Command::EndRenderPass);
|
mAllocator.Allocate<EndRenderPassCmd>(Command::EndRenderPass);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandBufferBuilder::EndRenderSubpass() {
|
void CommandBufferBuilder::EndRenderSubpass() {
|
||||||
allocator.Allocate<EndRenderSubpassCmd>(Command::EndRenderSubpass);
|
mAllocator.Allocate<EndRenderSubpassCmd>(Command::EndRenderSubpass);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandBufferBuilder::SetComputePipeline(ComputePipelineBase* pipeline) {
|
void CommandBufferBuilder::SetComputePipeline(ComputePipelineBase* pipeline) {
|
||||||
SetComputePipelineCmd* cmd = allocator.Allocate<SetComputePipelineCmd>(Command::SetComputePipeline);
|
SetComputePipelineCmd* cmd = mAllocator.Allocate<SetComputePipelineCmd>(Command::SetComputePipeline);
|
||||||
new(cmd) SetComputePipelineCmd;
|
new(cmd) SetComputePipelineCmd;
|
||||||
cmd->pipeline = pipeline;
|
cmd->pipeline = pipeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandBufferBuilder::SetRenderPipeline(RenderPipelineBase* pipeline) {
|
void CommandBufferBuilder::SetRenderPipeline(RenderPipelineBase* pipeline) {
|
||||||
SetRenderPipelineCmd* cmd = allocator.Allocate<SetRenderPipelineCmd>(Command::SetRenderPipeline);
|
SetRenderPipelineCmd* cmd = mAllocator.Allocate<SetRenderPipelineCmd>(Command::SetRenderPipeline);
|
||||||
new(cmd) SetRenderPipelineCmd;
|
new(cmd) SetRenderPipelineCmd;
|
||||||
cmd->pipeline = pipeline;
|
cmd->pipeline = pipeline;
|
||||||
}
|
}
|
||||||
|
@ -783,24 +783,24 @@ namespace backend {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetPushConstantsCmd* cmd = allocator.Allocate<SetPushConstantsCmd>(Command::SetPushConstants);
|
SetPushConstantsCmd* cmd = mAllocator.Allocate<SetPushConstantsCmd>(Command::SetPushConstants);
|
||||||
new(cmd) SetPushConstantsCmd;
|
new(cmd) SetPushConstantsCmd;
|
||||||
cmd->stages = stages;
|
cmd->stages = stages;
|
||||||
cmd->offset = offset;
|
cmd->offset = offset;
|
||||||
cmd->count = count;
|
cmd->count = count;
|
||||||
|
|
||||||
uint32_t* values = allocator.AllocateData<uint32_t>(count);
|
uint32_t* values = mAllocator.AllocateData<uint32_t>(count);
|
||||||
memcpy(values, data, count * sizeof(uint32_t));
|
memcpy(values, data, count * sizeof(uint32_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandBufferBuilder::SetStencilReference(uint32_t reference) {
|
void CommandBufferBuilder::SetStencilReference(uint32_t reference) {
|
||||||
SetStencilReferenceCmd* cmd = allocator.Allocate<SetStencilReferenceCmd>(Command::SetStencilReference);
|
SetStencilReferenceCmd* cmd = mAllocator.Allocate<SetStencilReferenceCmd>(Command::SetStencilReference);
|
||||||
new(cmd) SetStencilReferenceCmd;
|
new(cmd) SetStencilReferenceCmd;
|
||||||
cmd->reference = reference;
|
cmd->reference = reference;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandBufferBuilder::SetBlendColor(float r, float g, float b, float a) {
|
void CommandBufferBuilder::SetBlendColor(float r, float g, float b, float a) {
|
||||||
SetBlendColorCmd* cmd = allocator.Allocate<SetBlendColorCmd>(Command::SetBlendColor);
|
SetBlendColorCmd* cmd = mAllocator.Allocate<SetBlendColorCmd>(Command::SetBlendColor);
|
||||||
new(cmd) SetBlendColorCmd;
|
new(cmd) SetBlendColorCmd;
|
||||||
cmd->r = r;
|
cmd->r = r;
|
||||||
cmd->g = g;
|
cmd->g = g;
|
||||||
|
@ -814,7 +814,7 @@ namespace backend {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetBindGroupCmd* cmd = allocator.Allocate<SetBindGroupCmd>(Command::SetBindGroup);
|
SetBindGroupCmd* cmd = mAllocator.Allocate<SetBindGroupCmd>(Command::SetBindGroup);
|
||||||
new(cmd) SetBindGroupCmd;
|
new(cmd) SetBindGroupCmd;
|
||||||
cmd->index = groupIndex;
|
cmd->index = groupIndex;
|
||||||
cmd->group = group;
|
cmd->group = group;
|
||||||
|
@ -823,7 +823,7 @@ namespace backend {
|
||||||
void CommandBufferBuilder::SetIndexBuffer(BufferBase* buffer, uint32_t offset) {
|
void CommandBufferBuilder::SetIndexBuffer(BufferBase* buffer, uint32_t offset) {
|
||||||
// TODO(kainino@chromium.org): validation
|
// TODO(kainino@chromium.org): validation
|
||||||
|
|
||||||
SetIndexBufferCmd* cmd = allocator.Allocate<SetIndexBufferCmd>(Command::SetIndexBuffer);
|
SetIndexBufferCmd* cmd = mAllocator.Allocate<SetIndexBufferCmd>(Command::SetIndexBuffer);
|
||||||
new(cmd) SetIndexBufferCmd;
|
new(cmd) SetIndexBufferCmd;
|
||||||
cmd->buffer = buffer;
|
cmd->buffer = buffer;
|
||||||
cmd->offset = offset;
|
cmd->offset = offset;
|
||||||
|
@ -832,38 +832,38 @@ namespace backend {
|
||||||
void CommandBufferBuilder::SetVertexBuffers(uint32_t startSlot, uint32_t count, BufferBase* const* buffers, uint32_t const* offsets){
|
void CommandBufferBuilder::SetVertexBuffers(uint32_t startSlot, uint32_t count, BufferBase* const* buffers, uint32_t const* offsets){
|
||||||
// TODO(kainino@chromium.org): validation
|
// TODO(kainino@chromium.org): validation
|
||||||
|
|
||||||
SetVertexBuffersCmd* cmd = allocator.Allocate<SetVertexBuffersCmd>(Command::SetVertexBuffers);
|
SetVertexBuffersCmd* cmd = mAllocator.Allocate<SetVertexBuffersCmd>(Command::SetVertexBuffers);
|
||||||
new(cmd) SetVertexBuffersCmd;
|
new(cmd) SetVertexBuffersCmd;
|
||||||
cmd->startSlot = startSlot;
|
cmd->startSlot = startSlot;
|
||||||
cmd->count = count;
|
cmd->count = count;
|
||||||
|
|
||||||
Ref<BufferBase>* cmdBuffers = allocator.AllocateData<Ref<BufferBase>>(count);
|
Ref<BufferBase>* cmdBuffers = mAllocator.AllocateData<Ref<BufferBase>>(count);
|
||||||
for (size_t i = 0; i < count; ++i) {
|
for (size_t i = 0; i < count; ++i) {
|
||||||
new(&cmdBuffers[i]) Ref<BufferBase>(buffers[i]);
|
new(&cmdBuffers[i]) Ref<BufferBase>(buffers[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t* cmdOffsets = allocator.AllocateData<uint32_t>(count);
|
uint32_t* cmdOffsets = mAllocator.AllocateData<uint32_t>(count);
|
||||||
memcpy(cmdOffsets, offsets, count * sizeof(uint32_t));
|
memcpy(cmdOffsets, offsets, count * sizeof(uint32_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandBufferBuilder::TransitionBufferUsage(BufferBase* buffer, nxt::BufferUsageBit usage) {
|
void CommandBufferBuilder::TransitionBufferUsage(BufferBase* buffer, nxt::BufferUsageBit usage) {
|
||||||
TransitionBufferUsageCmd* cmd = allocator.Allocate<TransitionBufferUsageCmd>(Command::TransitionBufferUsage);
|
TransitionBufferUsageCmd* cmd = mAllocator.Allocate<TransitionBufferUsageCmd>(Command::TransitionBufferUsage);
|
||||||
new(cmd) TransitionBufferUsageCmd;
|
new(cmd) TransitionBufferUsageCmd;
|
||||||
cmd->buffer = buffer;
|
cmd->buffer = buffer;
|
||||||
cmd->usage = usage;
|
cmd->usage = usage;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandBufferBuilder::TransitionTextureUsage(TextureBase* texture, nxt::TextureUsageBit usage) {
|
void CommandBufferBuilder::TransitionTextureUsage(TextureBase* texture, nxt::TextureUsageBit usage) {
|
||||||
TransitionTextureUsageCmd* cmd = allocator.Allocate<TransitionTextureUsageCmd>(Command::TransitionTextureUsage);
|
TransitionTextureUsageCmd* cmd = mAllocator.Allocate<TransitionTextureUsageCmd>(Command::TransitionTextureUsage);
|
||||||
new(cmd) TransitionTextureUsageCmd;
|
new(cmd) TransitionTextureUsageCmd;
|
||||||
cmd->texture = texture;
|
cmd->texture = texture;
|
||||||
cmd->usage = usage;
|
cmd->usage = usage;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandBufferBuilder::MoveToIterator() {
|
void CommandBufferBuilder::MoveToIterator() {
|
||||||
if (!movedToIterator) {
|
if (!mWasMovedToIterator) {
|
||||||
iterator = std::move(allocator);
|
mIterator = std::move(mAllocator);
|
||||||
movedToIterator = true;
|
mWasMovedToIterator = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,9 +46,9 @@ namespace backend {
|
||||||
DeviceBase* GetDevice();
|
DeviceBase* GetDevice();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DeviceBase* device;
|
DeviceBase* mDevice;
|
||||||
std::set<BufferBase*> buffersTransitioned;
|
std::set<BufferBase*> mBuffersTransitioned;
|
||||||
std::set<TextureBase*> texturesTransitioned;
|
std::set<TextureBase*> mTexturesTransitioned;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CommandBufferBuilder : public Builder<CommandBufferBase> {
|
class CommandBufferBuilder : public Builder<CommandBufferBase> {
|
||||||
|
@ -101,11 +101,11 @@ namespace backend {
|
||||||
CommandBufferBase* GetResultImpl() override;
|
CommandBufferBase* GetResultImpl() override;
|
||||||
void MoveToIterator();
|
void MoveToIterator();
|
||||||
|
|
||||||
std::unique_ptr<CommandBufferStateTracker> state;
|
std::unique_ptr<CommandBufferStateTracker> mState;
|
||||||
CommandAllocator allocator;
|
CommandAllocator mAllocator;
|
||||||
CommandIterator iterator;
|
CommandIterator mIterator;
|
||||||
bool movedToIterator = false;
|
bool mWasMovedToIterator = false;
|
||||||
bool commandsAcquired = false;
|
bool mWereCommandsAcquired = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,21 +29,21 @@
|
||||||
#include "common/BitSetIterator.h"
|
#include "common/BitSetIterator.h"
|
||||||
|
|
||||||
namespace backend {
|
namespace backend {
|
||||||
CommandBufferStateTracker::CommandBufferStateTracker(CommandBufferBuilder* builder)
|
CommandBufferStateTracker::CommandBufferStateTracker(CommandBufferBuilder* mBuilder)
|
||||||
: builder(builder) {
|
: mBuilder(mBuilder) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandBufferStateTracker::HaveRenderPass() const {
|
bool CommandBufferStateTracker::HaveRenderPass() const {
|
||||||
return currentRenderPass != nullptr;
|
return mCurrentRenderPass != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandBufferStateTracker::HaveRenderSubpass() const {
|
bool CommandBufferStateTracker::HaveRenderSubpass() const {
|
||||||
return aspects[VALIDATION_ASPECT_RENDER_SUBPASS];
|
return mAspects[VALIDATION_ASPECT_RENDER_SUBPASS];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandBufferStateTracker::ValidateCanCopy() const {
|
bool CommandBufferStateTracker::ValidateCanCopy() const {
|
||||||
if (currentRenderPass) {
|
if (mCurrentRenderPass) {
|
||||||
builder->HandleError("Copy cannot occur during a render pass");
|
mBuilder->HandleError("Copy cannot occur during a render pass");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -51,7 +51,7 @@ namespace backend {
|
||||||
|
|
||||||
bool CommandBufferStateTracker::ValidateCanUseBufferAs(BufferBase* buffer, nxt::BufferUsageBit usage) const {
|
bool CommandBufferStateTracker::ValidateCanUseBufferAs(BufferBase* buffer, nxt::BufferUsageBit usage) const {
|
||||||
if (!BufferHasGuaranteedUsageBit(buffer, usage)) {
|
if (!BufferHasGuaranteedUsageBit(buffer, usage)) {
|
||||||
builder->HandleError("Buffer is not in the necessary usage");
|
mBuilder->HandleError("Buffer is not in the necessary usage");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -59,7 +59,7 @@ namespace backend {
|
||||||
|
|
||||||
bool CommandBufferStateTracker::ValidateCanUseTextureAs(TextureBase* texture, nxt::TextureUsageBit usage) const {
|
bool CommandBufferStateTracker::ValidateCanUseTextureAs(TextureBase* texture, nxt::TextureUsageBit usage) const {
|
||||||
if (!TextureHasGuaranteedUsageBit(texture, usage)) {
|
if (!TextureHasGuaranteedUsageBit(texture, usage)) {
|
||||||
builder->HandleError("Texture is not in the necessary usage");
|
mBuilder->HandleError("Texture is not in the necessary usage");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -69,18 +69,18 @@ namespace backend {
|
||||||
constexpr ValidationAspects requiredAspects =
|
constexpr ValidationAspects requiredAspects =
|
||||||
1 << VALIDATION_ASPECT_COMPUTE_PIPELINE | // implicitly requires COMPUTE_PASS
|
1 << VALIDATION_ASPECT_COMPUTE_PIPELINE | // implicitly requires COMPUTE_PASS
|
||||||
1 << VALIDATION_ASPECT_BIND_GROUPS;
|
1 << VALIDATION_ASPECT_BIND_GROUPS;
|
||||||
if ((requiredAspects & ~aspects).none()) {
|
if ((requiredAspects & ~mAspects).none()) {
|
||||||
// Fast return-true path if everything is good
|
// Fast return-true path if everything is good
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!aspects[VALIDATION_ASPECT_COMPUTE_PIPELINE]) {
|
if (!mAspects[VALIDATION_ASPECT_COMPUTE_PIPELINE]) {
|
||||||
builder->HandleError("No active compute pipeline");
|
mBuilder->HandleError("No active compute pipeline");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Compute the lazily computed aspects
|
// Compute the lazily computed mAspects
|
||||||
if (!RecomputeHaveAspectBindGroups()) {
|
if (!RecomputeHaveAspectBindGroups()) {
|
||||||
builder->HandleError("Bind group state not valid");
|
mBuilder->HandleError("Bind group state not valid");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -92,7 +92,7 @@ namespace backend {
|
||||||
1 << VALIDATION_ASPECT_RENDER_PIPELINE | // implicitly requires RENDER_SUBPASS
|
1 << VALIDATION_ASPECT_RENDER_PIPELINE | // implicitly requires RENDER_SUBPASS
|
||||||
1 << VALIDATION_ASPECT_BIND_GROUPS |
|
1 << VALIDATION_ASPECT_BIND_GROUPS |
|
||||||
1 << VALIDATION_ASPECT_VERTEX_BUFFERS;
|
1 << VALIDATION_ASPECT_VERTEX_BUFFERS;
|
||||||
if ((requiredAspects & ~aspects).none()) {
|
if ((requiredAspects & ~mAspects).none()) {
|
||||||
// Fast return-true path if everything is good
|
// Fast return-true path if everything is good
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -107,191 +107,191 @@ namespace backend {
|
||||||
1 << VALIDATION_ASPECT_BIND_GROUPS |
|
1 << VALIDATION_ASPECT_BIND_GROUPS |
|
||||||
1 << VALIDATION_ASPECT_VERTEX_BUFFERS |
|
1 << VALIDATION_ASPECT_VERTEX_BUFFERS |
|
||||||
1 << VALIDATION_ASPECT_INDEX_BUFFER;
|
1 << VALIDATION_ASPECT_INDEX_BUFFER;
|
||||||
if ((requiredAspects & ~aspects).none()) {
|
if ((requiredAspects & ~mAspects).none()) {
|
||||||
// Fast return-true path if everything is good
|
// Fast return-true path if everything is good
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!aspects[VALIDATION_ASPECT_INDEX_BUFFER]) {
|
if (!mAspects[VALIDATION_ASPECT_INDEX_BUFFER]) {
|
||||||
builder->HandleError("Cannot DrawElements without index buffer set");
|
mBuilder->HandleError("Cannot DrawElements without index buffer set");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return RevalidateCanDraw();
|
return RevalidateCanDraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandBufferStateTracker::ValidateEndCommandBuffer() const {
|
bool CommandBufferStateTracker::ValidateEndCommandBuffer() const {
|
||||||
if (currentRenderPass != nullptr) {
|
if (mCurrentRenderPass != nullptr) {
|
||||||
builder->HandleError("Can't end command buffer with an active render pass");
|
mBuilder->HandleError("Can't end command buffer with an active render pass");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (aspects[VALIDATION_ASPECT_COMPUTE_PASS]) {
|
if (mAspects[VALIDATION_ASPECT_COMPUTE_PASS]) {
|
||||||
builder->HandleError("Can't end command buffer with an active compute pass");
|
mBuilder->HandleError("Can't end command buffer with an active compute pass");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandBufferStateTracker::ValidateSetPushConstants(nxt::ShaderStageBit stages) {
|
bool CommandBufferStateTracker::ValidateSetPushConstants(nxt::ShaderStageBit stages) {
|
||||||
if (aspects[VALIDATION_ASPECT_COMPUTE_PASS]) {
|
if (mAspects[VALIDATION_ASPECT_COMPUTE_PASS]) {
|
||||||
if (stages & ~nxt::ShaderStageBit::Compute) {
|
if (stages & ~nxt::ShaderStageBit::Compute) {
|
||||||
builder->HandleError("SetPushConstants stage must be compute or 0 in compute passes");
|
mBuilder->HandleError("SetPushConstants stage must be compute or 0 in compute passes");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (aspects[VALIDATION_ASPECT_RENDER_SUBPASS]) {
|
} else if (mAspects[VALIDATION_ASPECT_RENDER_SUBPASS]) {
|
||||||
if (stages & ~(nxt::ShaderStageBit::Vertex | nxt::ShaderStageBit::Fragment)) {
|
if (stages & ~(nxt::ShaderStageBit::Vertex | nxt::ShaderStageBit::Fragment)) {
|
||||||
builder->HandleError("SetPushConstants stage must be a subset if (vertex|fragment) in subpasses");
|
mBuilder->HandleError("SetPushConstants stage must be a subset if (vertex|fragment) in subpasses");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
builder->HandleError("PushConstants must be set in either compute passes or subpasses");
|
mBuilder->HandleError("PushConstants must be set in either compute passes or subpasses");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandBufferStateTracker::BeginComputePass() {
|
bool CommandBufferStateTracker::BeginComputePass() {
|
||||||
if (currentRenderPass != nullptr) {
|
if (mCurrentRenderPass != nullptr) {
|
||||||
builder->HandleError("Cannot begin a compute pass while a render pass is active");
|
mBuilder->HandleError("Cannot begin a compute pass while a render pass is active");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
aspects.set(VALIDATION_ASPECT_COMPUTE_PASS);
|
mAspects.set(VALIDATION_ASPECT_COMPUTE_PASS);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandBufferStateTracker::EndComputePass() {
|
bool CommandBufferStateTracker::EndComputePass() {
|
||||||
if (!aspects[VALIDATION_ASPECT_COMPUTE_PASS]) {
|
if (!mAspects[VALIDATION_ASPECT_COMPUTE_PASS]) {
|
||||||
builder->HandleError("Can't end a compute pass without beginning one");
|
mBuilder->HandleError("Can't end a compute pass without beginning one");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
aspects.reset(VALIDATION_ASPECT_COMPUTE_PASS);
|
mAspects.reset(VALIDATION_ASPECT_COMPUTE_PASS);
|
||||||
UnsetPipeline();
|
UnsetPipeline();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandBufferStateTracker::BeginSubpass() {
|
bool CommandBufferStateTracker::BeginSubpass() {
|
||||||
if (currentRenderPass == nullptr) {
|
if (mCurrentRenderPass == nullptr) {
|
||||||
builder->HandleError("Can't begin a subpass without an active render pass");
|
mBuilder->HandleError("Can't begin a subpass without an active render pass");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (aspects[VALIDATION_ASPECT_RENDER_SUBPASS]) {
|
if (mAspects[VALIDATION_ASPECT_RENDER_SUBPASS]) {
|
||||||
builder->HandleError("Can't begin a subpass without ending the previous subpass");
|
mBuilder->HandleError("Can't begin a subpass without ending the previous subpass");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (currentSubpass >= currentRenderPass->GetSubpassCount()) {
|
if (mCurrentSubpass >= mCurrentRenderPass->GetSubpassCount()) {
|
||||||
builder->HandleError("Can't begin a subpass beyond the last subpass");
|
mBuilder->HandleError("Can't begin a subpass beyond the last subpass");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& subpassInfo = currentRenderPass->GetSubpassInfo(currentSubpass);
|
auto& subpassInfo = mCurrentRenderPass->GetSubpassInfo(mCurrentSubpass);
|
||||||
for (auto location : IterateBitSet(subpassInfo.colorAttachmentsSet)) {
|
for (auto location : IterateBitSet(subpassInfo.colorAttachmentsSet)) {
|
||||||
auto attachmentSlot = subpassInfo.colorAttachments[location];
|
auto attachmentSlot = subpassInfo.colorAttachments[location];
|
||||||
auto* tv = currentFramebuffer->GetTextureView(attachmentSlot);
|
auto* tv = mCurrentFramebuffer->GetTextureView(attachmentSlot);
|
||||||
auto* texture = tv->GetTexture();
|
auto* texture = tv->GetTexture();
|
||||||
if (!EnsureTextureUsage(texture, nxt::TextureUsageBit::OutputAttachment)) {
|
if (!EnsureTextureUsage(texture, nxt::TextureUsageBit::OutputAttachment)) {
|
||||||
builder->HandleError("Unable to ensure texture has OutputAttachment usage");
|
mBuilder->HandleError("Unable to ensure texture has OutputAttachment usage");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
texturesAttached.insert(texture);
|
mTexturesAttached.insert(texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
aspects.set(VALIDATION_ASPECT_RENDER_SUBPASS);
|
mAspects.set(VALIDATION_ASPECT_RENDER_SUBPASS);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandBufferStateTracker::EndSubpass() {
|
bool CommandBufferStateTracker::EndSubpass() {
|
||||||
if (!aspects[VALIDATION_ASPECT_RENDER_SUBPASS]) {
|
if (!mAspects[VALIDATION_ASPECT_RENDER_SUBPASS]) {
|
||||||
builder->HandleError("Can't end a subpass without beginning one");
|
mBuilder->HandleError("Can't end a subpass without beginning one");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ASSERT(currentRenderPass != nullptr);
|
ASSERT(mCurrentRenderPass != nullptr);
|
||||||
|
|
||||||
auto& subpassInfo = currentRenderPass->GetSubpassInfo(currentSubpass);
|
auto& subpassInfo = mCurrentRenderPass->GetSubpassInfo(mCurrentSubpass);
|
||||||
for (auto location : IterateBitSet(subpassInfo.colorAttachmentsSet)) {
|
for (auto location : IterateBitSet(subpassInfo.colorAttachmentsSet)) {
|
||||||
auto attachmentSlot = subpassInfo.colorAttachments[location];
|
auto attachmentSlot = subpassInfo.colorAttachments[location];
|
||||||
auto* tv = currentFramebuffer->GetTextureView(attachmentSlot);
|
auto* tv = mCurrentFramebuffer->GetTextureView(attachmentSlot);
|
||||||
auto* texture = tv->GetTexture();
|
auto* texture = tv->GetTexture();
|
||||||
if (texture->IsFrozen()) {
|
if (texture->IsFrozen()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Everything in texturesAttached should be for the current render subpass.
|
// Everything in mTexturesAttached should be for the current render subpass.
|
||||||
texturesAttached.clear();
|
mTexturesAttached.clear();
|
||||||
|
|
||||||
currentSubpass += 1;
|
mCurrentSubpass += 1;
|
||||||
inputsSet.reset();
|
mInputsSet.reset();
|
||||||
aspects.reset(VALIDATION_ASPECT_RENDER_SUBPASS);
|
mAspects.reset(VALIDATION_ASPECT_RENDER_SUBPASS);
|
||||||
UnsetPipeline();
|
UnsetPipeline();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandBufferStateTracker::BeginRenderPass(RenderPassBase* renderPass, FramebufferBase* framebuffer) {
|
bool CommandBufferStateTracker::BeginRenderPass(RenderPassBase* renderPass, FramebufferBase* framebuffer) {
|
||||||
if (aspects[VALIDATION_ASPECT_COMPUTE_PASS]) {
|
if (mAspects[VALIDATION_ASPECT_COMPUTE_PASS]) {
|
||||||
builder->HandleError("Cannot begin a render pass while a compute pass is active");
|
mBuilder->HandleError("Cannot begin a render pass while a compute pass is active");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (currentRenderPass != nullptr) {
|
if (mCurrentRenderPass != nullptr) {
|
||||||
builder->HandleError("A render pass is already active");
|
mBuilder->HandleError("A render pass is already active");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ASSERT(!aspects[VALIDATION_ASPECT_RENDER_SUBPASS]);
|
ASSERT(!mAspects[VALIDATION_ASPECT_RENDER_SUBPASS]);
|
||||||
if (!framebuffer->GetRenderPass()->IsCompatibleWith(renderPass)) {
|
if (!framebuffer->GetRenderPass()->IsCompatibleWith(renderPass)) {
|
||||||
builder->HandleError("Framebuffer is incompatible with this render pass");
|
mBuilder->HandleError("Framebuffer is incompatible with this render pass");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
currentRenderPass = renderPass;
|
mCurrentRenderPass = renderPass;
|
||||||
currentFramebuffer = framebuffer;
|
mCurrentFramebuffer = framebuffer;
|
||||||
currentSubpass = 0;
|
mCurrentSubpass = 0;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandBufferStateTracker::EndRenderPass() {
|
bool CommandBufferStateTracker::EndRenderPass() {
|
||||||
if (currentRenderPass == nullptr) {
|
if (mCurrentRenderPass == nullptr) {
|
||||||
builder->HandleError("No render pass is currently active");
|
mBuilder->HandleError("No render pass is currently active");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (aspects[VALIDATION_ASPECT_RENDER_SUBPASS]) {
|
if (mAspects[VALIDATION_ASPECT_RENDER_SUBPASS]) {
|
||||||
builder->HandleError("Can't end a render pass while a subpass is active");
|
mBuilder->HandleError("Can't end a render pass while a subpass is active");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (currentSubpass < currentRenderPass->GetSubpassCount() - 1) {
|
if (mCurrentSubpass < mCurrentRenderPass->GetSubpassCount() - 1) {
|
||||||
builder->HandleError("Can't end a render pass before the last subpass");
|
mBuilder->HandleError("Can't end a render pass before the last subpass");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
currentRenderPass = nullptr;
|
mCurrentRenderPass = nullptr;
|
||||||
currentFramebuffer = nullptr;
|
mCurrentFramebuffer = nullptr;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandBufferStateTracker::SetComputePipeline(ComputePipelineBase* pipeline) {
|
bool CommandBufferStateTracker::SetComputePipeline(ComputePipelineBase* pipeline) {
|
||||||
if (!aspects[VALIDATION_ASPECT_COMPUTE_PASS]) {
|
if (!mAspects[VALIDATION_ASPECT_COMPUTE_PASS]) {
|
||||||
builder->HandleError("A compute pass must be active when a compute pipeline is set");
|
mBuilder->HandleError("A compute pass must be active when a compute pipeline is set");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (currentRenderPass) {
|
if (mCurrentRenderPass) {
|
||||||
builder->HandleError("Can't use a compute pipeline while a render pass is active");
|
mBuilder->HandleError("Can't use a compute pipeline while a render pass is active");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
aspects.set(VALIDATION_ASPECT_COMPUTE_PIPELINE);
|
mAspects.set(VALIDATION_ASPECT_COMPUTE_PIPELINE);
|
||||||
SetPipelineCommon(pipeline);
|
SetPipelineCommon(pipeline);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandBufferStateTracker::SetRenderPipeline(RenderPipelineBase* pipeline) {
|
bool CommandBufferStateTracker::SetRenderPipeline(RenderPipelineBase* pipeline) {
|
||||||
if (!aspects[VALIDATION_ASPECT_RENDER_SUBPASS]) {
|
if (!mAspects[VALIDATION_ASPECT_RENDER_SUBPASS]) {
|
||||||
builder->HandleError("A render subpass must be active when a render pipeline is set");
|
mBuilder->HandleError("A render subpass must be active when a render pipeline is set");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!pipeline->GetRenderPass()->IsCompatibleWith(currentRenderPass)) {
|
if (!pipeline->GetRenderPass()->IsCompatibleWith(mCurrentRenderPass)) {
|
||||||
builder->HandleError("Pipeline is incompatible with this render pass");
|
mBuilder->HandleError("Pipeline is incompatible with this render pass");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
aspects.set(VALIDATION_ASPECT_RENDER_PIPELINE);
|
mAspects.set(VALIDATION_ASPECT_RENDER_PIPELINE);
|
||||||
lastRenderPipeline = pipeline;
|
mLastRenderPipeline = pipeline;
|
||||||
SetPipelineCommon(pipeline);
|
SetPipelineCommon(pipeline);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -300,77 +300,77 @@ namespace backend {
|
||||||
if (!ValidateBindGroupUsages(bindgroup)) {
|
if (!ValidateBindGroupUsages(bindgroup)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bindgroupsSet.set(index);
|
mBindgroupsSet.set(index);
|
||||||
bindgroups[index] = bindgroup;
|
mBindgroups[index] = bindgroup;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandBufferStateTracker::SetIndexBuffer(BufferBase* buffer) {
|
bool CommandBufferStateTracker::SetIndexBuffer(BufferBase* buffer) {
|
||||||
if (!HavePipeline()) {
|
if (!HavePipeline()) {
|
||||||
builder->HandleError("Can't set the index buffer without a pipeline");
|
mBuilder->HandleError("Can't set the index buffer without a pipeline");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto usage = nxt::BufferUsageBit::Index;
|
auto usage = nxt::BufferUsageBit::Index;
|
||||||
if (!BufferHasGuaranteedUsageBit(buffer, usage)) {
|
if (!BufferHasGuaranteedUsageBit(buffer, usage)) {
|
||||||
builder->HandleError("Buffer needs the index usage bit to be guaranteed");
|
mBuilder->HandleError("Buffer needs the index usage bit to be guaranteed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
aspects.set(VALIDATION_ASPECT_INDEX_BUFFER);
|
mAspects.set(VALIDATION_ASPECT_INDEX_BUFFER);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandBufferStateTracker::SetVertexBuffer(uint32_t index, BufferBase* buffer) {
|
bool CommandBufferStateTracker::SetVertexBuffer(uint32_t index, BufferBase* buffer) {
|
||||||
if (!HavePipeline()) {
|
if (!HavePipeline()) {
|
||||||
builder->HandleError("Can't set vertex buffers without a pipeline");
|
mBuilder->HandleError("Can't set vertex buffers without a pipeline");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto usage = nxt::BufferUsageBit::Vertex;
|
auto usage = nxt::BufferUsageBit::Vertex;
|
||||||
if (!BufferHasGuaranteedUsageBit(buffer, usage)) {
|
if (!BufferHasGuaranteedUsageBit(buffer, usage)) {
|
||||||
builder->HandleError("Buffer needs vertex usage bit to be guaranteed");
|
mBuilder->HandleError("Buffer needs vertex usage bit to be guaranteed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inputsSet.set(index);
|
mInputsSet.set(index);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandBufferStateTracker::TransitionBufferUsage(BufferBase* buffer, nxt::BufferUsageBit usage) {
|
bool CommandBufferStateTracker::TransitionBufferUsage(BufferBase* buffer, nxt::BufferUsageBit usage) {
|
||||||
if (!buffer->IsTransitionPossible(usage)) {
|
if (!buffer->IsTransitionPossible(usage)) {
|
||||||
if (buffer->IsFrozen()) {
|
if (buffer->IsFrozen()) {
|
||||||
builder->HandleError("Buffer transition not possible (usage is frozen)");
|
mBuilder->HandleError("Buffer transition not possible (usage is frozen)");
|
||||||
} else if (!BufferBase::IsUsagePossible(buffer->GetAllowedUsage(), usage)) {
|
} else if (!BufferBase::IsUsagePossible(buffer->GetAllowedUsage(), usage)) {
|
||||||
builder->HandleError("Buffer transition not possible (usage not allowed)");
|
mBuilder->HandleError("Buffer transition not possible (usage not allowed)");
|
||||||
} else {
|
} else {
|
||||||
builder->HandleError("Buffer transition not possible");
|
mBuilder->HandleError("Buffer transition not possible");
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mostRecentBufferUsages[buffer] = usage;
|
mMostRecentBufferUsages[buffer] = usage;
|
||||||
buffersTransitioned.insert(buffer);
|
mBuffersTransitioned.insert(buffer);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandBufferStateTracker::TransitionTextureUsage(TextureBase* texture, nxt::TextureUsageBit usage) {
|
bool CommandBufferStateTracker::TransitionTextureUsage(TextureBase* texture, nxt::TextureUsageBit usage) {
|
||||||
if (!IsExplicitTextureTransitionPossible(texture, usage)) {
|
if (!IsExplicitTextureTransitionPossible(texture, usage)) {
|
||||||
if (texture->IsFrozen()) {
|
if (texture->IsFrozen()) {
|
||||||
builder->HandleError("Texture transition not possible (usage is frozen)");
|
mBuilder->HandleError("Texture transition not possible (usage is frozen)");
|
||||||
} else if (!TextureBase::IsUsagePossible(texture->GetAllowedUsage(), usage)) {
|
} else if (!TextureBase::IsUsagePossible(texture->GetAllowedUsage(), usage)) {
|
||||||
builder->HandleError("Texture transition not possible (usage not allowed)");
|
mBuilder->HandleError("Texture transition not possible (usage not allowed)");
|
||||||
} else if (texturesAttached.find(texture) != texturesAttached.end()) {
|
} else if (mTexturesAttached.find(texture) != mTexturesAttached.end()) {
|
||||||
builder->HandleError("Texture transition not possible (texture is in use as a framebuffer attachment)");
|
mBuilder->HandleError("Texture transition not possible (texture is in use as a framebuffer attachment)");
|
||||||
} else {
|
} else {
|
||||||
builder->HandleError("Texture transition not possible");
|
mBuilder->HandleError("Texture transition not possible");
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mostRecentTextureUsages[texture] = usage;
|
mMostRecentTextureUsages[texture] = usage;
|
||||||
texturesTransitioned.insert(texture);
|
mTexturesTransitioned.insert(texture);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -381,8 +381,8 @@ namespace backend {
|
||||||
if (!IsInternalTextureTransitionPossible(texture, usage)) {
|
if (!IsInternalTextureTransitionPossible(texture, usage)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
mostRecentTextureUsages[texture] = usage;
|
mMostRecentTextureUsages[texture] = usage;
|
||||||
texturesTransitioned.insert(texture);
|
mTexturesTransitioned.insert(texture);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -391,8 +391,8 @@ namespace backend {
|
||||||
if (buffer->HasFrozenUsage(usage)) {
|
if (buffer->HasFrozenUsage(usage)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
auto it = mostRecentBufferUsages.find(buffer);
|
auto it = mMostRecentBufferUsages.find(buffer);
|
||||||
return it != mostRecentBufferUsages.end() && (it->second & usage);
|
return it != mMostRecentBufferUsages.end() && (it->second & usage);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandBufferStateTracker::TextureHasGuaranteedUsageBit(TextureBase* texture, nxt::TextureUsageBit usage) const {
|
bool CommandBufferStateTracker::TextureHasGuaranteedUsageBit(TextureBase* texture, nxt::TextureUsageBit usage) const {
|
||||||
|
@ -400,13 +400,13 @@ namespace backend {
|
||||||
if (texture->HasFrozenUsage(usage)) {
|
if (texture->HasFrozenUsage(usage)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
auto it = mostRecentTextureUsages.find(texture);
|
auto it = mMostRecentTextureUsages.find(texture);
|
||||||
return it != mostRecentTextureUsages.end() && (it->second & usage);
|
return it != mMostRecentTextureUsages.end() && (it->second & usage);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandBufferStateTracker::IsInternalTextureTransitionPossible(TextureBase* texture, nxt::TextureUsageBit usage) const {
|
bool CommandBufferStateTracker::IsInternalTextureTransitionPossible(TextureBase* texture, nxt::TextureUsageBit usage) const {
|
||||||
ASSERT(usage != nxt::TextureUsageBit::None && nxt::HasZeroOrOneBits(usage));
|
ASSERT(usage != nxt::TextureUsageBit::None && nxt::HasZeroOrOneBits(usage));
|
||||||
if (texturesAttached.find(texture) != texturesAttached.end()) {
|
if (mTexturesAttached.find(texture) != mTexturesAttached.end()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return texture->IsTransitionPossible(usage);
|
return texture->IsTransitionPossible(usage);
|
||||||
|
@ -422,33 +422,33 @@ namespace backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandBufferStateTracker::RecomputeHaveAspectBindGroups() {
|
bool CommandBufferStateTracker::RecomputeHaveAspectBindGroups() {
|
||||||
if (aspects[VALIDATION_ASPECT_BIND_GROUPS]) {
|
if (mAspects[VALIDATION_ASPECT_BIND_GROUPS]) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Assumes we have a pipeline already
|
// Assumes we have a pipeline already
|
||||||
if (!bindgroupsSet.all()) {
|
if (!mBindgroupsSet.all()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < bindgroups.size(); ++i) {
|
for (size_t i = 0; i < mBindgroups.size(); ++i) {
|
||||||
if (auto* bindgroup = bindgroups[i]) {
|
if (auto* bindgroup = mBindgroups[i]) {
|
||||||
// TODO(kainino@chromium.org): bind group compatibility
|
// TODO(kainino@chromium.org): bind group compatibility
|
||||||
if (bindgroup->GetLayout() != lastPipeline->GetLayout()->GetBindGroupLayout(i)) {
|
if (bindgroup->GetLayout() != mLastPipeline->GetLayout()->GetBindGroupLayout(i)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
aspects.set(VALIDATION_ASPECT_BIND_GROUPS);
|
mAspects.set(VALIDATION_ASPECT_BIND_GROUPS);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandBufferStateTracker::RecomputeHaveAspectVertexBuffers() {
|
bool CommandBufferStateTracker::RecomputeHaveAspectVertexBuffers() {
|
||||||
if (aspects[VALIDATION_ASPECT_VERTEX_BUFFERS]) {
|
if (mAspects[VALIDATION_ASPECT_VERTEX_BUFFERS]) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Assumes we have a pipeline already
|
// Assumes we have a pipeline already
|
||||||
auto requiredInputs = lastRenderPipeline->GetInputState()->GetInputsSetMask();
|
auto requiredInputs = mLastRenderPipeline->GetInputState()->GetInputsSetMask();
|
||||||
if ((inputsSet & requiredInputs) == requiredInputs) {
|
if ((mInputsSet & requiredInputs) == requiredInputs) {
|
||||||
aspects.set(VALIDATION_ASPECT_VERTEX_BUFFERS);
|
mAspects.set(VALIDATION_ASPECT_VERTEX_BUFFERS);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -458,7 +458,7 @@ namespace backend {
|
||||||
constexpr ValidationAspects pipelineAspects =
|
constexpr ValidationAspects pipelineAspects =
|
||||||
1 << VALIDATION_ASPECT_COMPUTE_PIPELINE |
|
1 << VALIDATION_ASPECT_COMPUTE_PIPELINE |
|
||||||
1 << VALIDATION_ASPECT_RENDER_PIPELINE;
|
1 << VALIDATION_ASPECT_RENDER_PIPELINE;
|
||||||
return (aspects & pipelineAspects).any();
|
return (mAspects & pipelineAspects).any();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandBufferStateTracker::ValidateBindGroupUsages(BindGroupBase* group) const {
|
bool CommandBufferStateTracker::ValidateBindGroupUsages(BindGroupBase* group) const {
|
||||||
|
@ -489,7 +489,7 @@ namespace backend {
|
||||||
|
|
||||||
auto buffer = group->GetBindingAsBufferView(i)->GetBuffer();
|
auto buffer = group->GetBindingAsBufferView(i)->GetBuffer();
|
||||||
if (!BufferHasGuaranteedUsageBit(buffer, requiredUsage)) {
|
if (!BufferHasGuaranteedUsageBit(buffer, requiredUsage)) {
|
||||||
builder->HandleError("Can't guarantee buffer usage needed by bind group");
|
mBuilder->HandleError("Can't guarantee buffer usage needed by bind group");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -500,7 +500,7 @@ namespace backend {
|
||||||
|
|
||||||
auto texture = group->GetBindingAsTextureView(i)->GetTexture();
|
auto texture = group->GetBindingAsTextureView(i)->GetTexture();
|
||||||
if (!TextureHasGuaranteedUsageBit(texture, requiredUsage)) {
|
if (!TextureHasGuaranteedUsageBit(texture, requiredUsage)) {
|
||||||
builder->HandleError("Can't guarantee texture usage needed by bind group");
|
mBuilder->HandleError("Can't guarantee texture usage needed by bind group");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -513,17 +513,17 @@ namespace backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandBufferStateTracker::RevalidateCanDraw() {
|
bool CommandBufferStateTracker::RevalidateCanDraw() {
|
||||||
if (!aspects[VALIDATION_ASPECT_RENDER_PIPELINE]) {
|
if (!mAspects[VALIDATION_ASPECT_RENDER_PIPELINE]) {
|
||||||
builder->HandleError("No active render pipeline");
|
mBuilder->HandleError("No active render pipeline");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Compute the lazily computed aspects
|
// Compute the lazily computed mAspects
|
||||||
if (!RecomputeHaveAspectBindGroups()) {
|
if (!RecomputeHaveAspectBindGroups()) {
|
||||||
builder->HandleError("Bind group state not valid");
|
mBuilder->HandleError("Bind group state not valid");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!RecomputeHaveAspectVertexBuffers()) {
|
if (!RecomputeHaveAspectVertexBuffers()) {
|
||||||
builder->HandleError("Some vertex buffers are not set");
|
mBuilder->HandleError("Some vertex buffers are not set");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -532,17 +532,17 @@ namespace backend {
|
||||||
void CommandBufferStateTracker::SetPipelineCommon(PipelineBase* pipeline) {
|
void CommandBufferStateTracker::SetPipelineCommon(PipelineBase* pipeline) {
|
||||||
PipelineLayoutBase* layout = pipeline->GetLayout();
|
PipelineLayoutBase* layout = pipeline->GetLayout();
|
||||||
|
|
||||||
aspects.reset(VALIDATION_ASPECT_BIND_GROUPS);
|
mAspects.reset(VALIDATION_ASPECT_BIND_GROUPS);
|
||||||
aspects.reset(VALIDATION_ASPECT_VERTEX_BUFFERS);
|
mAspects.reset(VALIDATION_ASPECT_VERTEX_BUFFERS);
|
||||||
// Reset bindgroups but mark unused bindgroups as valid
|
// Reset bindgroups but mark unused bindgroups as valid
|
||||||
bindgroupsSet = ~layout->GetBindGroupsLayoutMask();
|
mBindgroupsSet = ~layout->GetBindGroupsLayoutMask();
|
||||||
|
|
||||||
// Only bindgroups that were not the same layout in the last pipeline need to be set again.
|
// Only bindgroups that were not the same layout in the last pipeline need to be set again.
|
||||||
if (lastPipeline) {
|
if (mLastPipeline) {
|
||||||
bindgroupsSet |= layout->InheritedGroupsMask(lastPipeline->GetLayout());
|
mBindgroupsSet |= layout->InheritedGroupsMask(mLastPipeline->GetLayout());
|
||||||
}
|
}
|
||||||
|
|
||||||
lastPipeline = pipeline;
|
mLastPipeline = pipeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandBufferStateTracker::UnsetPipeline() {
|
void CommandBufferStateTracker::UnsetPipeline() {
|
||||||
|
@ -552,7 +552,7 @@ namespace backend {
|
||||||
1 << VALIDATION_ASPECT_BIND_GROUPS |
|
1 << VALIDATION_ASPECT_BIND_GROUPS |
|
||||||
1 << VALIDATION_ASPECT_VERTEX_BUFFERS |
|
1 << VALIDATION_ASPECT_VERTEX_BUFFERS |
|
||||||
1 << VALIDATION_ASPECT_INDEX_BUFFER;
|
1 << VALIDATION_ASPECT_INDEX_BUFFER;
|
||||||
aspects &= ~pipelineDependentAspects;
|
mAspects &= ~pipelineDependentAspects;
|
||||||
bindgroups.fill(nullptr);
|
mBindgroups.fill(nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,9 +59,9 @@ namespace backend {
|
||||||
// These collections are copied to the CommandBuffer at build time.
|
// These collections are copied to the CommandBuffer at build time.
|
||||||
// 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.
|
||||||
std::set<BufferBase*> buffersTransitioned;
|
std::set<BufferBase*> mBuffersTransitioned;
|
||||||
std::set<TextureBase*> texturesTransitioned;
|
std::set<TextureBase*> mTexturesTransitioned;
|
||||||
std::set<TextureBase*> texturesAttached;
|
std::set<TextureBase*> mTexturesAttached;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum ValidationAspect {
|
enum ValidationAspect {
|
||||||
|
@ -94,22 +94,22 @@ namespace backend {
|
||||||
void SetPipelineCommon(PipelineBase* pipeline);
|
void SetPipelineCommon(PipelineBase* pipeline);
|
||||||
void UnsetPipeline();
|
void UnsetPipeline();
|
||||||
|
|
||||||
CommandBufferBuilder* builder;
|
CommandBufferBuilder* mBuilder;
|
||||||
|
|
||||||
ValidationAspects aspects;
|
ValidationAspects mAspects;
|
||||||
|
|
||||||
std::bitset<kMaxBindGroups> bindgroupsSet;
|
std::bitset<kMaxBindGroups> mBindgroupsSet;
|
||||||
std::array<BindGroupBase*, kMaxBindGroups> bindgroups = {};
|
std::array<BindGroupBase*, kMaxBindGroups> mBindgroups = {};
|
||||||
std::bitset<kMaxVertexInputs> inputsSet;
|
std::bitset<kMaxVertexInputs> mInputsSet;
|
||||||
PipelineBase* lastPipeline = nullptr;
|
PipelineBase* mLastPipeline = nullptr;
|
||||||
RenderPipelineBase* lastRenderPipeline = nullptr;
|
RenderPipelineBase* mLastRenderPipeline = nullptr;
|
||||||
|
|
||||||
std::map<BufferBase*, nxt::BufferUsageBit> mostRecentBufferUsages;
|
std::map<BufferBase*, nxt::BufferUsageBit> mMostRecentBufferUsages;
|
||||||
std::map<TextureBase*, nxt::TextureUsageBit> mostRecentTextureUsages;
|
std::map<TextureBase*, nxt::TextureUsageBit> mMostRecentTextureUsages;
|
||||||
|
|
||||||
RenderPassBase* currentRenderPass = nullptr;
|
RenderPassBase* mCurrentRenderPass = nullptr;
|
||||||
FramebufferBase* currentFramebuffer = nullptr;
|
FramebufferBase* mCurrentFramebuffer = nullptr;
|
||||||
uint32_t currentSubpass = 0;
|
uint32_t mCurrentSubpass = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ namespace backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
ComputePipelineBase* ComputePipelineBuilder::GetResultImpl() {
|
ComputePipelineBase* ComputePipelineBuilder::GetResultImpl() {
|
||||||
return device->CreateComputePipeline(this);
|
return mDevice->CreateComputePipeline(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,26 +21,26 @@ namespace backend {
|
||||||
// DepthStencilStateBase
|
// DepthStencilStateBase
|
||||||
|
|
||||||
DepthStencilStateBase::DepthStencilStateBase(DepthStencilStateBuilder* builder)
|
DepthStencilStateBase::DepthStencilStateBase(DepthStencilStateBuilder* builder)
|
||||||
: depthInfo(builder->depthInfo), stencilInfo(builder->stencilInfo) {
|
: mDepthInfo(builder->mDepthInfo), mStencilInfo(builder->mStencilInfo) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DepthStencilStateBase::StencilTestEnabled() const {
|
bool DepthStencilStateBase::StencilTestEnabled() const {
|
||||||
return stencilInfo.back.compareFunction != nxt::CompareFunction::Always ||
|
return mStencilInfo.back.compareFunction != nxt::CompareFunction::Always ||
|
||||||
stencilInfo.back.stencilFail != nxt::StencilOperation::Keep ||
|
mStencilInfo.back.stencilFail != nxt::StencilOperation::Keep ||
|
||||||
stencilInfo.back.depthFail != nxt::StencilOperation::Keep ||
|
mStencilInfo.back.depthFail != nxt::StencilOperation::Keep ||
|
||||||
stencilInfo.back.depthStencilPass != nxt::StencilOperation::Keep ||
|
mStencilInfo.back.depthStencilPass != nxt::StencilOperation::Keep ||
|
||||||
stencilInfo.front.compareFunction != nxt::CompareFunction::Always ||
|
mStencilInfo.front.compareFunction != nxt::CompareFunction::Always ||
|
||||||
stencilInfo.front.stencilFail != nxt::StencilOperation::Keep ||
|
mStencilInfo.front.stencilFail != nxt::StencilOperation::Keep ||
|
||||||
stencilInfo.front.depthFail != nxt::StencilOperation::Keep ||
|
mStencilInfo.front.depthFail != nxt::StencilOperation::Keep ||
|
||||||
stencilInfo.front.depthStencilPass != nxt::StencilOperation::Keep;
|
mStencilInfo.front.depthStencilPass != nxt::StencilOperation::Keep;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DepthStencilStateBase::DepthInfo& DepthStencilStateBase::GetDepth() const {
|
const DepthStencilStateBase::DepthInfo& DepthStencilStateBase::GetDepth() const {
|
||||||
return depthInfo;
|
return mDepthInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DepthStencilStateBase::StencilInfo& DepthStencilStateBase::GetStencil() const {
|
const DepthStencilStateBase::StencilInfo& DepthStencilStateBase::GetStencil() const {
|
||||||
return stencilInfo;
|
return mStencilInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
// DepthStencilStateBuilder
|
// DepthStencilStateBuilder
|
||||||
|
@ -57,29 +57,29 @@ namespace backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
DepthStencilStateBase* DepthStencilStateBuilder::GetResultImpl() {
|
DepthStencilStateBase* DepthStencilStateBuilder::GetResultImpl() {
|
||||||
return device->CreateDepthStencilState(this);
|
return mDevice->CreateDepthStencilState(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DepthStencilStateBuilder::SetDepthCompareFunction(nxt::CompareFunction depthCompareFunction) {
|
void DepthStencilStateBuilder::SetDepthCompareFunction(nxt::CompareFunction depthCompareFunction) {
|
||||||
if ((propertiesSet & DEPTH_STENCIL_STATE_PROPERTY_DEPTH_COMPARE_FUNCTION) != 0) {
|
if ((mPropertiesSet & DEPTH_STENCIL_STATE_PROPERTY_DEPTH_COMPARE_FUNCTION) != 0) {
|
||||||
HandleError("Depth compare property set multiple times");
|
HandleError("Depth compare property set multiple times");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
propertiesSet |= DEPTH_STENCIL_STATE_PROPERTY_DEPTH_COMPARE_FUNCTION;
|
mPropertiesSet |= DEPTH_STENCIL_STATE_PROPERTY_DEPTH_COMPARE_FUNCTION;
|
||||||
|
|
||||||
depthInfo.compareFunction = depthCompareFunction;
|
mDepthInfo.compareFunction = depthCompareFunction;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DepthStencilStateBuilder::SetDepthWriteEnabled(bool enabled) {
|
void DepthStencilStateBuilder::SetDepthWriteEnabled(bool enabled) {
|
||||||
if ((propertiesSet & DEPTH_STENCIL_STATE_PROPERTY_DEPTH_WRITE_ENABLED) != 0) {
|
if ((mPropertiesSet & DEPTH_STENCIL_STATE_PROPERTY_DEPTH_WRITE_ENABLED) != 0) {
|
||||||
HandleError("Depth write enabled property set multiple times");
|
HandleError("Depth write enabled property set multiple times");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
propertiesSet |= DEPTH_STENCIL_STATE_PROPERTY_DEPTH_WRITE_ENABLED;
|
mPropertiesSet |= DEPTH_STENCIL_STATE_PROPERTY_DEPTH_WRITE_ENABLED;
|
||||||
|
|
||||||
depthInfo.depthWriteEnabled = enabled;
|
mDepthInfo.depthWriteEnabled = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DepthStencilStateBuilder::SetStencilFunction(nxt::Face face, nxt::CompareFunction stencilCompareFunction,
|
void DepthStencilStateBuilder::SetStencilFunction(nxt::Face face, nxt::CompareFunction stencilCompareFunction,
|
||||||
|
@ -90,42 +90,42 @@ namespace backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (face & nxt::Face::Back) {
|
if (face & nxt::Face::Back) {
|
||||||
if ((propertiesSet & DEPTH_STENCIL_STATE_PROPERTY_STENCIL_BACK_FUNCTION) != 0) {
|
if ((mPropertiesSet & DEPTH_STENCIL_STATE_PROPERTY_STENCIL_BACK_FUNCTION) != 0) {
|
||||||
HandleError("Stencil back function property set multiple times");
|
HandleError("Stencil back function property set multiple times");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
propertiesSet |= DEPTH_STENCIL_STATE_PROPERTY_STENCIL_BACK_FUNCTION;
|
mPropertiesSet |= DEPTH_STENCIL_STATE_PROPERTY_STENCIL_BACK_FUNCTION;
|
||||||
|
|
||||||
stencilInfo.back.compareFunction = stencilCompareFunction;
|
mStencilInfo.back.compareFunction = stencilCompareFunction;
|
||||||
stencilInfo.back.stencilFail = stencilFail;
|
mStencilInfo.back.stencilFail = stencilFail;
|
||||||
stencilInfo.back.depthFail = depthFail;
|
mStencilInfo.back.depthFail = depthFail;
|
||||||
stencilInfo.back.depthStencilPass = depthStencilPass;
|
mStencilInfo.back.depthStencilPass = depthStencilPass;
|
||||||
}
|
}
|
||||||
if (face & nxt::Face::Front) {
|
if (face & nxt::Face::Front) {
|
||||||
if ((propertiesSet & DEPTH_STENCIL_STATE_PROPERTY_STENCIL_FRONT_FUNCTION) != 0) {
|
if ((mPropertiesSet & DEPTH_STENCIL_STATE_PROPERTY_STENCIL_FRONT_FUNCTION) != 0) {
|
||||||
HandleError("Stencil front function property set multiple times");
|
HandleError("Stencil front function property set multiple times");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
propertiesSet |= DEPTH_STENCIL_STATE_PROPERTY_STENCIL_FRONT_FUNCTION;
|
mPropertiesSet |= DEPTH_STENCIL_STATE_PROPERTY_STENCIL_FRONT_FUNCTION;
|
||||||
|
|
||||||
stencilInfo.front.compareFunction = stencilCompareFunction;
|
mStencilInfo.front.compareFunction = stencilCompareFunction;
|
||||||
stencilInfo.front.stencilFail = stencilFail;
|
mStencilInfo.front.stencilFail = stencilFail;
|
||||||
stencilInfo.front.depthFail = depthFail;
|
mStencilInfo.front.depthFail = depthFail;
|
||||||
stencilInfo.front.depthStencilPass = depthStencilPass;
|
mStencilInfo.front.depthStencilPass = depthStencilPass;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DepthStencilStateBuilder::SetStencilMask(uint32_t readMask, uint32_t writeMask) {
|
void DepthStencilStateBuilder::SetStencilMask(uint32_t readMask, uint32_t writeMask) {
|
||||||
if ((propertiesSet & DEPTH_STENCIL_STATE_PROPERTY_STENCIL_MASK) != 0) {
|
if ((mPropertiesSet & DEPTH_STENCIL_STATE_PROPERTY_STENCIL_MASK) != 0) {
|
||||||
HandleError("Stencilmask property set multiple times");
|
HandleError("Stencilmask property set multiple times");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
propertiesSet |= DEPTH_STENCIL_STATE_PROPERTY_STENCIL_MASK;
|
mPropertiesSet |= DEPTH_STENCIL_STATE_PROPERTY_STENCIL_MASK;
|
||||||
stencilInfo.readMask = readMask;
|
mStencilInfo.readMask = readMask;
|
||||||
stencilInfo.writeMask = writeMask;
|
mStencilInfo.writeMask = writeMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,8 +52,8 @@ namespace backend {
|
||||||
const StencilInfo& GetStencil() const;
|
const StencilInfo& GetStencil() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DepthInfo depthInfo;
|
DepthInfo mDepthInfo;
|
||||||
StencilInfo stencilInfo;
|
StencilInfo mStencilInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DepthStencilStateBuilder : public Builder<DepthStencilStateBase> {
|
class DepthStencilStateBuilder : public Builder<DepthStencilStateBase> {
|
||||||
|
@ -72,10 +72,10 @@ namespace backend {
|
||||||
|
|
||||||
DepthStencilStateBase* GetResultImpl() override;
|
DepthStencilStateBase* GetResultImpl() override;
|
||||||
|
|
||||||
int propertiesSet = 0;
|
int mPropertiesSet = 0;
|
||||||
|
|
||||||
DepthStencilStateBase::DepthInfo depthInfo;
|
DepthStencilStateBase::DepthInfo mDepthInfo;
|
||||||
DepthStencilStateBase::StencilInfo stencilInfo;
|
DepthStencilStateBase::StencilInfo mStencilInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,22 +49,22 @@ namespace backend {
|
||||||
// DeviceBase
|
// DeviceBase
|
||||||
|
|
||||||
DeviceBase::DeviceBase() {
|
DeviceBase::DeviceBase() {
|
||||||
caches = new DeviceBase::Caches();
|
mCaches = new DeviceBase::Caches();
|
||||||
}
|
}
|
||||||
|
|
||||||
DeviceBase::~DeviceBase() {
|
DeviceBase::~DeviceBase() {
|
||||||
delete caches;
|
delete mCaches;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceBase::HandleError(const char* message) {
|
void DeviceBase::HandleError(const char* message) {
|
||||||
if (errorCallback) {
|
if (mErrorCallback) {
|
||||||
errorCallback(message, errorUserdata);
|
mErrorCallback(message, mErrorUserdata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceBase::SetErrorCallback(nxt::DeviceErrorCallback callback, nxt::CallbackUserdata userdata) {
|
void DeviceBase::SetErrorCallback(nxt::DeviceErrorCallback callback, nxt::CallbackUserdata userdata) {
|
||||||
this->errorCallback = callback;
|
mErrorCallback = callback;
|
||||||
this->errorUserdata = userdata;
|
mErrorUserdata = userdata;
|
||||||
}
|
}
|
||||||
|
|
||||||
DeviceBase* DeviceBase::GetDevice() {
|
DeviceBase* DeviceBase::GetDevice() {
|
||||||
|
@ -76,18 +76,18 @@ namespace backend {
|
||||||
// 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
|
||||||
// const pointer set. That's why we do a const_cast here, but the blueprint won't be
|
// const pointer set. That's why we do a const_cast here, but the blueprint won't be
|
||||||
// modified.
|
// modified.
|
||||||
auto iter = caches->bindGroupLayouts.find(const_cast<BindGroupLayoutBase*>(blueprint));
|
auto iter = mCaches->bindGroupLayouts.find(const_cast<BindGroupLayoutBase*>(blueprint));
|
||||||
if (iter != caches->bindGroupLayouts.end()) {
|
if (iter != mCaches->bindGroupLayouts.end()) {
|
||||||
return *iter;
|
return *iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
BindGroupLayoutBase* backendObj = CreateBindGroupLayout(builder);
|
BindGroupLayoutBase* backendObj = CreateBindGroupLayout(builder);
|
||||||
caches->bindGroupLayouts.insert(backendObj);
|
mCaches->bindGroupLayouts.insert(backendObj);
|
||||||
return backendObj;
|
return backendObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceBase::UncacheBindGroupLayout(BindGroupLayoutBase* obj) {
|
void DeviceBase::UncacheBindGroupLayout(BindGroupLayoutBase* obj) {
|
||||||
caches->bindGroupLayouts.erase(obj);
|
mCaches->bindGroupLayouts.erase(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
BindGroupBuilder* DeviceBase::CreateBindGroupBuilder() {
|
BindGroupBuilder* DeviceBase::CreateBindGroupBuilder() {
|
||||||
|
@ -147,14 +147,14 @@ namespace backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceBase::Reference() {
|
void DeviceBase::Reference() {
|
||||||
ASSERT(refCount != 0);
|
ASSERT(mRefCount != 0);
|
||||||
refCount++;
|
mRefCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceBase::Release() {
|
void DeviceBase::Release() {
|
||||||
ASSERT(refCount != 0);
|
ASSERT(mRefCount != 0);
|
||||||
refCount--;
|
mRefCount--;
|
||||||
if (refCount == 0) {
|
if (mRefCount == 0) {
|
||||||
delete this;
|
delete this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,7 +78,6 @@ namespace backend {
|
||||||
BindGroupLayoutBuilder* CreateBindGroupLayoutBuilder();
|
BindGroupLayoutBuilder* CreateBindGroupLayoutBuilder();
|
||||||
BlendStateBuilder* CreateBlendStateBuilder();
|
BlendStateBuilder* CreateBlendStateBuilder();
|
||||||
BufferBuilder* CreateBufferBuilder();
|
BufferBuilder* CreateBufferBuilder();
|
||||||
BufferViewBuilder* CreateBufferViewBuilder();
|
|
||||||
CommandBufferBuilder* CreateCommandBufferBuilder();
|
CommandBufferBuilder* CreateCommandBufferBuilder();
|
||||||
ComputePipelineBuilder* CreateComputePipelineBuilder();
|
ComputePipelineBuilder* CreateComputePipelineBuilder();
|
||||||
DepthStencilStateBuilder* CreateDepthStencilStateBuilder();
|
DepthStencilStateBuilder* CreateDepthStencilStateBuilder();
|
||||||
|
@ -94,7 +93,6 @@ namespace backend {
|
||||||
TextureBuilder* CreateTextureBuilder();
|
TextureBuilder* CreateTextureBuilder();
|
||||||
|
|
||||||
void Tick();
|
void Tick();
|
||||||
void CopyBindGroups(uint32_t start, uint32_t count, BindGroupBase* source, BindGroupBase* target);
|
|
||||||
void SetErrorCallback(nxt::DeviceErrorCallback callback, nxt::CallbackUserdata userdata);
|
void SetErrorCallback(nxt::DeviceErrorCallback callback, nxt::CallbackUserdata userdata);
|
||||||
void Reference();
|
void Reference();
|
||||||
void Release();
|
void Release();
|
||||||
|
@ -103,11 +101,11 @@ namespace backend {
|
||||||
// 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;
|
||||||
Caches* caches = nullptr;
|
Caches* mCaches = nullptr;
|
||||||
|
|
||||||
nxt::DeviceErrorCallback errorCallback = nullptr;
|
nxt::DeviceErrorCallback mErrorCallback = nullptr;
|
||||||
nxt::CallbackUserdata errorUserdata = 0;
|
nxt::CallbackUserdata mErrorUserdata = 0;
|
||||||
uint32_t refCount = 1;
|
uint32_t mRefCount = 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,49 +25,49 @@ namespace backend {
|
||||||
// Framebuffer
|
// Framebuffer
|
||||||
|
|
||||||
FramebufferBase::FramebufferBase(FramebufferBuilder* builder)
|
FramebufferBase::FramebufferBase(FramebufferBuilder* builder)
|
||||||
: device(builder->device), renderPass(std::move(builder->renderPass)),
|
: mDevice(builder->mDevice), mRenderPass(std::move(builder->mRenderPass)),
|
||||||
width(builder->width), height(builder->height), textureViews(std::move(builder->textureViews)),
|
mWidth(builder->mWidth), mHeight(builder->mHeight), mTextureViews(std::move(builder->mTextureViews)),
|
||||||
clearColors(textureViews.size()), clearDepthStencils(textureViews.size()) {
|
mClearColors(mTextureViews.size()), mClearDepthStencils(mTextureViews.size()) {
|
||||||
}
|
}
|
||||||
|
|
||||||
DeviceBase* FramebufferBase::GetDevice() {
|
DeviceBase* FramebufferBase::GetDevice() {
|
||||||
return device;
|
return mDevice;
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderPassBase* FramebufferBase::GetRenderPass() {
|
RenderPassBase* FramebufferBase::GetRenderPass() {
|
||||||
return renderPass.Get();
|
return mRenderPass.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureViewBase* FramebufferBase::GetTextureView(uint32_t attachmentSlot) {
|
TextureViewBase* FramebufferBase::GetTextureView(uint32_t attachmentSlot) {
|
||||||
ASSERT(attachmentSlot < textureViews.size());
|
ASSERT(attachmentSlot < mTextureViews.size());
|
||||||
return textureViews[attachmentSlot].Get();
|
return mTextureViews[attachmentSlot].Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
FramebufferBase::ClearColor FramebufferBase::GetClearColor(uint32_t attachmentSlot) {
|
FramebufferBase::ClearColor FramebufferBase::GetClearColor(uint32_t attachmentSlot) {
|
||||||
ASSERT(attachmentSlot < clearColors.size());
|
ASSERT(attachmentSlot < mClearColors.size());
|
||||||
return clearColors[attachmentSlot];
|
return mClearColors[attachmentSlot];
|
||||||
}
|
}
|
||||||
|
|
||||||
FramebufferBase::ClearDepthStencil FramebufferBase::GetClearDepthStencil(uint32_t attachmentSlot) {
|
FramebufferBase::ClearDepthStencil FramebufferBase::GetClearDepthStencil(uint32_t attachmentSlot) {
|
||||||
ASSERT(attachmentSlot < clearDepthStencils.size());
|
ASSERT(attachmentSlot < mClearDepthStencils.size());
|
||||||
return clearDepthStencils[attachmentSlot];
|
return mClearDepthStencils[attachmentSlot];
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t FramebufferBase::GetWidth() const {
|
uint32_t FramebufferBase::GetWidth() const {
|
||||||
return width;
|
return mWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t FramebufferBase::GetHeight() const {
|
uint32_t FramebufferBase::GetHeight() const {
|
||||||
return height;
|
return mHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramebufferBase::AttachmentSetClearColor(uint32_t attachmentSlot, float clearR, float clearG, float clearB, float clearA) {
|
void FramebufferBase::AttachmentSetClearColor(uint32_t attachmentSlot, float clearR, float clearG, float clearB, float clearA) {
|
||||||
if (attachmentSlot >= renderPass->GetAttachmentCount()) {
|
if (attachmentSlot >= mRenderPass->GetAttachmentCount()) {
|
||||||
device->HandleError("Framebuffer attachment out of bounds");
|
mDevice->HandleError("Framebuffer attachment out of bounds");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ASSERT(attachmentSlot < clearColors.size());
|
ASSERT(attachmentSlot < mClearColors.size());
|
||||||
auto& c = clearColors[attachmentSlot];
|
auto& c = mClearColors[attachmentSlot];
|
||||||
c.color[0] = clearR;
|
c.color[0] = clearR;
|
||||||
c.color[1] = clearG;
|
c.color[1] = clearG;
|
||||||
c.color[2] = clearB;
|
c.color[2] = clearB;
|
||||||
|
@ -75,12 +75,12 @@ namespace backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramebufferBase::AttachmentSetClearDepthStencil(uint32_t attachmentSlot, float clearDepth, uint32_t clearStencil) {
|
void FramebufferBase::AttachmentSetClearDepthStencil(uint32_t attachmentSlot, float clearDepth, uint32_t clearStencil) {
|
||||||
if (attachmentSlot >= renderPass->GetAttachmentCount()) {
|
if (attachmentSlot >= mRenderPass->GetAttachmentCount()) {
|
||||||
device->HandleError("Framebuffer attachment out of bounds");
|
mDevice->HandleError("Framebuffer attachment out of bounds");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ASSERT(attachmentSlot < clearDepthStencils.size());
|
ASSERT(attachmentSlot < mClearDepthStencils.size());
|
||||||
auto& c = clearDepthStencils[attachmentSlot];
|
auto& c = mClearDepthStencils[attachmentSlot];
|
||||||
c.depth = clearDepth;
|
c.depth = clearDepth;
|
||||||
c.stencil = clearStencil;
|
c.stencil = clearStencil;
|
||||||
}
|
}
|
||||||
|
@ -98,30 +98,30 @@ namespace backend {
|
||||||
|
|
||||||
FramebufferBase* FramebufferBuilder::GetResultImpl() {
|
FramebufferBase* FramebufferBuilder::GetResultImpl() {
|
||||||
constexpr int requiredProperties = FRAMEBUFFER_PROPERTY_RENDER_PASS | FRAMEBUFFER_PROPERTY_DIMENSIONS;
|
constexpr int requiredProperties = FRAMEBUFFER_PROPERTY_RENDER_PASS | FRAMEBUFFER_PROPERTY_DIMENSIONS;
|
||||||
if ((propertiesSet & requiredProperties) != requiredProperties) {
|
if ((mPropertiesSet & requiredProperties) != requiredProperties) {
|
||||||
HandleError("Framebuffer missing properties");
|
HandleError("Framebuffer missing properties");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& textureView : textureViews) {
|
for (auto& textureView : mTextureViews) {
|
||||||
if (!textureView) {
|
if (!textureView) {
|
||||||
HandleError("Framebuffer attachment not set");
|
HandleError("Framebuffer attachment not set");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(cwallez@chromium.org): Adjust for the mip-level once that is supported.
|
// TODO(cwallez@chromium.org): Adjust for the mip-level once that is supported.
|
||||||
if (textureView->GetTexture()->GetWidth() != width ||
|
if (textureView->GetTexture()->GetWidth() != mWidth ||
|
||||||
textureView->GetTexture()->GetHeight() != height) {
|
textureView->GetTexture()->GetHeight() != mHeight) {
|
||||||
HandleError("Framebuffer size doesn't match attachment size");
|
HandleError("Framebuffer size doesn't match attachment size");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return device->CreateFramebuffer(this);
|
return mDevice->CreateFramebuffer(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramebufferBuilder::SetRenderPass(RenderPassBase* renderPass) {
|
void FramebufferBuilder::SetRenderPass(RenderPassBase* renderPass) {
|
||||||
if ((propertiesSet & FRAMEBUFFER_PROPERTY_RENDER_PASS) != 0) {
|
if ((mPropertiesSet & FRAMEBUFFER_PROPERTY_RENDER_PASS) != 0) {
|
||||||
HandleError("Framebuffer render pass property set multiple times");
|
HandleError("Framebuffer render pass property set multiple times");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -131,36 +131,36 @@ namespace backend {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->renderPass = renderPass;
|
mRenderPass = renderPass;
|
||||||
this->textureViews.resize(renderPass->GetAttachmentCount());
|
mTextureViews.resize(renderPass->GetAttachmentCount());
|
||||||
propertiesSet |= FRAMEBUFFER_PROPERTY_RENDER_PASS;
|
mPropertiesSet |= FRAMEBUFFER_PROPERTY_RENDER_PASS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramebufferBuilder::SetDimensions(uint32_t width, uint32_t height) {
|
void FramebufferBuilder::SetDimensions(uint32_t width, uint32_t height) {
|
||||||
if ((propertiesSet & FRAMEBUFFER_PROPERTY_DIMENSIONS) != 0) {
|
if ((mPropertiesSet & FRAMEBUFFER_PROPERTY_DIMENSIONS) != 0) {
|
||||||
HandleError("Framebuffer dimensions property set multiple times");
|
HandleError("Framebuffer dimensions property set multiple times");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->width = width;
|
mWidth = width;
|
||||||
this->height = height;
|
mHeight = height;
|
||||||
propertiesSet |= FRAMEBUFFER_PROPERTY_DIMENSIONS;
|
mPropertiesSet |= FRAMEBUFFER_PROPERTY_DIMENSIONS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramebufferBuilder::SetAttachment(uint32_t attachmentSlot, TextureViewBase* textureView) {
|
void FramebufferBuilder::SetAttachment(uint32_t attachmentSlot, TextureViewBase* textureView) {
|
||||||
if ((propertiesSet & FRAMEBUFFER_PROPERTY_RENDER_PASS) == 0) {
|
if ((mPropertiesSet & FRAMEBUFFER_PROPERTY_RENDER_PASS) == 0) {
|
||||||
HandleError("Render pass must be set before framebuffer attachments");
|
HandleError("Render pass must be set before framebuffer attachments");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (attachmentSlot >= textureViews.size()) {
|
if (attachmentSlot >= mTextureViews.size()) {
|
||||||
HandleError("Attachment slot out of bounds");
|
HandleError("Attachment slot out of bounds");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (textureViews[attachmentSlot]) {
|
if (mTextureViews[attachmentSlot]) {
|
||||||
HandleError("Framebuffer attachment[i] set multiple times");
|
HandleError("Framebuffer attachment[i] set multiple times");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto& attachmentInfo = renderPass->GetAttachmentInfo(attachmentSlot);
|
const auto& attachmentInfo = mRenderPass->GetAttachmentInfo(attachmentSlot);
|
||||||
const auto* texture = textureView->GetTexture();
|
const auto* texture = textureView->GetTexture();
|
||||||
if (attachmentInfo.format != texture->GetFormat()) {
|
if (attachmentInfo.format != texture->GetFormat()) {
|
||||||
HandleError("Texture format does not match attachment format");
|
HandleError("Texture format does not match attachment format");
|
||||||
|
@ -168,6 +168,6 @@ namespace backend {
|
||||||
}
|
}
|
||||||
// TODO(kainino@chromium.org): also check attachment samples, etc.
|
// TODO(kainino@chromium.org): also check attachment samples, etc.
|
||||||
|
|
||||||
textureViews[attachmentSlot] = textureView;
|
mTextureViews[attachmentSlot] = textureView;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,13 +52,13 @@ namespace backend {
|
||||||
void AttachmentSetClearDepthStencil(uint32_t attachmentSlot, float clearDepth, uint32_t clearStencil);
|
void AttachmentSetClearDepthStencil(uint32_t attachmentSlot, float clearDepth, uint32_t clearStencil);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DeviceBase* device;
|
DeviceBase* mDevice;
|
||||||
Ref<RenderPassBase> renderPass;
|
Ref<RenderPassBase> mRenderPass;
|
||||||
uint32_t width = 0;
|
uint32_t mWidth = 0;
|
||||||
uint32_t height = 0;
|
uint32_t mHeight = 0;
|
||||||
std::vector<Ref<TextureViewBase>> textureViews;
|
std::vector<Ref<TextureViewBase>> mTextureViews;
|
||||||
std::vector<ClearColor> clearColors;
|
std::vector<ClearColor> mClearColors;
|
||||||
std::vector<ClearDepthStencil> clearDepthStencils;
|
std::vector<ClearDepthStencil> mClearDepthStencils;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FramebufferBuilder : public Builder<FramebufferBase> {
|
class FramebufferBuilder : public Builder<FramebufferBase> {
|
||||||
|
@ -74,11 +74,11 @@ namespace backend {
|
||||||
private:
|
private:
|
||||||
friend class FramebufferBase;
|
friend class FramebufferBase;
|
||||||
|
|
||||||
Ref<RenderPassBase> renderPass;
|
Ref<RenderPassBase> mRenderPass;
|
||||||
uint32_t width = 0;
|
uint32_t mWidth = 0;
|
||||||
uint32_t height = 0;
|
uint32_t mHeight = 0;
|
||||||
std::vector<Ref<TextureViewBase>> textureViews;
|
std::vector<Ref<TextureViewBase>> mTextureViews;
|
||||||
int propertiesSet = 0;
|
int mPropertiesSet = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,28 +62,28 @@ namespace backend {
|
||||||
// InputStateBase
|
// InputStateBase
|
||||||
|
|
||||||
InputStateBase::InputStateBase(InputStateBuilder* builder) {
|
InputStateBase::InputStateBase(InputStateBuilder* builder) {
|
||||||
attributesSetMask = builder->attributesSetMask;
|
mAttributesSetMask = builder->mAttributesSetMask;
|
||||||
attributeInfos = builder->attributeInfos;
|
mAttributeInfos = builder->mAttributeInfos;
|
||||||
inputsSetMask = builder->inputsSetMask;
|
mInputsSetMask = builder->mInputsSetMask;
|
||||||
inputInfos = builder->inputInfos;
|
mInputInfos = builder->mInputInfos;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::bitset<kMaxVertexAttributes>& InputStateBase::GetAttributesSetMask() const {
|
const std::bitset<kMaxVertexAttributes>& InputStateBase::GetAttributesSetMask() const {
|
||||||
return attributesSetMask;
|
return mAttributesSetMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
const InputStateBase::AttributeInfo& InputStateBase::GetAttribute(uint32_t location) const {
|
const InputStateBase::AttributeInfo& InputStateBase::GetAttribute(uint32_t location) const {
|
||||||
ASSERT(attributesSetMask[location]);
|
ASSERT(mAttributesSetMask[location]);
|
||||||
return attributeInfos[location];
|
return mAttributeInfos[location];
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::bitset<kMaxVertexInputs>& InputStateBase::GetInputsSetMask() const {
|
const std::bitset<kMaxVertexInputs>& InputStateBase::GetInputsSetMask() const {
|
||||||
return inputsSetMask;
|
return mInputsSetMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
const InputStateBase::InputInfo& InputStateBase::GetInput(uint32_t slot) const {
|
const InputStateBase::InputInfo& InputStateBase::GetInput(uint32_t slot) const {
|
||||||
ASSERT(inputsSetMask[slot]);
|
ASSERT(mInputsSetMask[slot]);
|
||||||
return inputInfos[slot];
|
return mInputInfos[slot];
|
||||||
}
|
}
|
||||||
|
|
||||||
// InputStateBuilder
|
// InputStateBuilder
|
||||||
|
@ -93,14 +93,14 @@ namespace backend {
|
||||||
|
|
||||||
InputStateBase* InputStateBuilder::GetResultImpl() {
|
InputStateBase* InputStateBuilder::GetResultImpl() {
|
||||||
for (uint32_t location = 0; location < kMaxVertexAttributes; ++location) {
|
for (uint32_t location = 0; location < kMaxVertexAttributes; ++location) {
|
||||||
if (attributesSetMask[location] &&
|
if (mAttributesSetMask[location] &&
|
||||||
!inputsSetMask[attributeInfos[location].bindingSlot]) {
|
!mInputsSetMask[mAttributeInfos[location].bindingSlot]) {
|
||||||
HandleError("Attribute uses unset input");
|
HandleError("Attribute uses unset input");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return device->CreateInputState(this);
|
return mDevice->CreateInputState(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputStateBuilder::SetAttribute(uint32_t shaderLocation,
|
void InputStateBuilder::SetAttribute(uint32_t shaderLocation,
|
||||||
|
@ -113,13 +113,13 @@ namespace backend {
|
||||||
HandleError("Binding slot out of bounds");
|
HandleError("Binding slot out of bounds");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (attributesSetMask[shaderLocation]) {
|
if (mAttributesSetMask[shaderLocation]) {
|
||||||
HandleError("Setting already set attribute");
|
HandleError("Setting already set attribute");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
attributesSetMask.set(shaderLocation);
|
mAttributesSetMask.set(shaderLocation);
|
||||||
auto& info = attributeInfos[shaderLocation];
|
auto& info = mAttributeInfos[shaderLocation];
|
||||||
info.bindingSlot = bindingSlot;
|
info.bindingSlot = bindingSlot;
|
||||||
info.format = format;
|
info.format = format;
|
||||||
info.offset = offset;
|
info.offset = offset;
|
||||||
|
@ -131,13 +131,13 @@ namespace backend {
|
||||||
HandleError("Setting input out of bounds");
|
HandleError("Setting input out of bounds");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (inputsSetMask[bindingSlot]) {
|
if (mInputsSetMask[bindingSlot]) {
|
||||||
HandleError("Setting already set input");
|
HandleError("Setting already set input");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
inputsSetMask.set(bindingSlot);
|
mInputsSetMask.set(bindingSlot);
|
||||||
auto& info = inputInfos[bindingSlot];
|
auto& info = mInputInfos[bindingSlot];
|
||||||
info.stride = stride;
|
info.stride = stride;
|
||||||
info.stepMode = stepMode;
|
info.stepMode = stepMode;
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,10 +52,10 @@ namespace backend {
|
||||||
const InputInfo& GetInput(uint32_t slot) const;
|
const InputInfo& GetInput(uint32_t slot) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::bitset<kMaxVertexAttributes> attributesSetMask;
|
std::bitset<kMaxVertexAttributes> mAttributesSetMask;
|
||||||
std::array<AttributeInfo, kMaxVertexAttributes> attributeInfos;
|
std::array<AttributeInfo, kMaxVertexAttributes> mAttributeInfos;
|
||||||
std::bitset<kMaxVertexInputs> inputsSetMask;
|
std::bitset<kMaxVertexInputs> mInputsSetMask;
|
||||||
std::array<InputInfo, kMaxVertexInputs> inputInfos;
|
std::array<InputInfo, kMaxVertexInputs> mInputInfos;
|
||||||
};
|
};
|
||||||
|
|
||||||
class InputStateBuilder : public Builder<InputStateBase> {
|
class InputStateBuilder : public Builder<InputStateBase> {
|
||||||
|
@ -73,10 +73,10 @@ namespace backend {
|
||||||
|
|
||||||
InputStateBase* GetResultImpl() override;
|
InputStateBase* GetResultImpl() override;
|
||||||
|
|
||||||
std::bitset<kMaxVertexAttributes> attributesSetMask;
|
std::bitset<kMaxVertexAttributes> mAttributesSetMask;
|
||||||
std::array<InputStateBase::AttributeInfo, kMaxVertexAttributes> attributeInfos;
|
std::array<InputStateBase::AttributeInfo, kMaxVertexAttributes> mAttributeInfos;
|
||||||
std::bitset<kMaxVertexInputs> inputsSetMask;
|
std::bitset<kMaxVertexInputs> mInputsSetMask;
|
||||||
std::array<InputStateBase::InputInfo, kMaxVertexInputs> inputInfos;
|
std::array<InputStateBase::InputInfo, kMaxVertexInputs> mInputInfos;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,26 +43,26 @@ namespace backend {
|
||||||
public:
|
public:
|
||||||
T& operator[](nxt::ShaderStage stage) {
|
T& operator[](nxt::ShaderStage stage) {
|
||||||
NXT_ASSERT(static_cast<uint32_t>(stage) < kNumStages);
|
NXT_ASSERT(static_cast<uint32_t>(stage) < kNumStages);
|
||||||
return data[static_cast<uint32_t>(stage)];
|
return mData[static_cast<uint32_t>(stage)];
|
||||||
}
|
}
|
||||||
const T& operator[](nxt::ShaderStage stage) const {
|
const T& operator[](nxt::ShaderStage stage) const {
|
||||||
NXT_ASSERT(static_cast<uint32_t>(stage) < kNumStages);
|
NXT_ASSERT(static_cast<uint32_t>(stage) < kNumStages);
|
||||||
return data[static_cast<uint32_t>(stage)];
|
return mData[static_cast<uint32_t>(stage)];
|
||||||
}
|
}
|
||||||
|
|
||||||
T& operator[](nxt::ShaderStageBit stageBit) {
|
T& operator[](nxt::ShaderStageBit stageBit) {
|
||||||
uint32_t bit = static_cast<uint32_t>(stageBit);
|
uint32_t bit = static_cast<uint32_t>(stageBit);
|
||||||
NXT_ASSERT(bit != 0 && IsPowerOfTwo(bit) && bit <= (1 << kNumStages));
|
NXT_ASSERT(bit != 0 && IsPowerOfTwo(bit) && bit <= (1 << kNumStages));
|
||||||
return data[Log2(bit)];
|
return mData[Log2(bit)];
|
||||||
}
|
}
|
||||||
const T& operator[](nxt::ShaderStageBit stageBit) const {
|
const T& operator[](nxt::ShaderStageBit stageBit) const {
|
||||||
uint32_t bit = static_cast<uint32_t>(stageBit);
|
uint32_t bit = static_cast<uint32_t>(stageBit);
|
||||||
NXT_ASSERT(bit != 0 && IsPowerOfTwo(bit) && bit <= (1 << kNumStages));
|
NXT_ASSERT(bit != 0 && IsPowerOfTwo(bit) && bit <= (1 << kNumStages));
|
||||||
return data[Log2(bit)];
|
return mData[Log2(bit)];
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::array<T, kNumStages> data;
|
std::array<T, kNumStages> mData;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,9 +26,9 @@ namespace backend {
|
||||||
// PipelineBase
|
// PipelineBase
|
||||||
|
|
||||||
PipelineBase::PipelineBase(PipelineBuilder* builder)
|
PipelineBase::PipelineBase(PipelineBuilder* builder)
|
||||||
: stageMask(builder->stageMask), layout(std::move(builder->layout)) {
|
: mStageMask(builder->mStageMask), mLayout(std::move(builder->mLayout)) {
|
||||||
if (!layout) {
|
if (!mLayout) {
|
||||||
layout = builder->GetParentBuilder()->GetDevice()->CreatePipelineLayoutBuilder()->GetResult();
|
mLayout = builder->GetParentBuilder()->GetDevice()->CreatePipelineLayoutBuilder()->GetResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto FillPushConstants = [](const ShaderModuleBase* module, PushConstantInfo* info) {
|
auto FillPushConstants = [](const ShaderModuleBase* module, PushConstantInfo* info) {
|
||||||
|
@ -48,67 +48,67 @@ namespace backend {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
for (auto stageBit : IterateStages(builder->stageMask)) {
|
for (auto stageBit : IterateStages(builder->mStageMask)) {
|
||||||
if (!builder->stages[stageBit].module->IsCompatibleWithPipelineLayout(layout.Get())) {
|
if (!builder->mStages[stageBit].module->IsCompatibleWithPipelineLayout(mLayout.Get())) {
|
||||||
builder->GetParentBuilder()->HandleError("Stage not compatible with layout");
|
builder->GetParentBuilder()->HandleError("Stage not compatible with layout");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
FillPushConstants(builder->stages[stageBit].module.Get(), &pushConstants[stageBit]);
|
FillPushConstants(builder->mStages[stageBit].module.Get(), &mPushConstants[stageBit]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const PipelineBase::PushConstantInfo& PipelineBase::GetPushConstants(nxt::ShaderStage stage) const {
|
const PipelineBase::PushConstantInfo& PipelineBase::GetPushConstants(nxt::ShaderStage stage) const {
|
||||||
return pushConstants[stage];
|
return mPushConstants[stage];
|
||||||
}
|
}
|
||||||
|
|
||||||
nxt::ShaderStageBit PipelineBase::GetStageMask() const {
|
nxt::ShaderStageBit PipelineBase::GetStageMask() const {
|
||||||
return stageMask;
|
return mStageMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
PipelineLayoutBase* PipelineBase::GetLayout() {
|
PipelineLayoutBase* PipelineBase::GetLayout() {
|
||||||
return layout.Get();
|
return mLayout.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
// PipelineBuilder
|
// PipelineBuilder
|
||||||
|
|
||||||
PipelineBuilder::PipelineBuilder(BuilderBase* parentBuilder)
|
PipelineBuilder::PipelineBuilder(BuilderBase* parentBuilder)
|
||||||
: parentBuilder(parentBuilder), stageMask(static_cast<nxt::ShaderStageBit>(0)) {
|
: mParentBuilder(parentBuilder), mStageMask(static_cast<nxt::ShaderStageBit>(0)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const PipelineBuilder::StageInfo& PipelineBuilder::GetStageInfo(nxt::ShaderStage stage) const {
|
const PipelineBuilder::StageInfo& PipelineBuilder::GetStageInfo(nxt::ShaderStage stage) const {
|
||||||
ASSERT(stageMask & StageBit(stage));
|
ASSERT(mStageMask & StageBit(stage));
|
||||||
return stages[stage];
|
return mStages[stage];
|
||||||
}
|
}
|
||||||
|
|
||||||
BuilderBase* PipelineBuilder::GetParentBuilder() const {
|
BuilderBase* PipelineBuilder::GetParentBuilder() const {
|
||||||
return parentBuilder;
|
return mParentBuilder;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PipelineBuilder::SetLayout(PipelineLayoutBase* layout) {
|
void PipelineBuilder::SetLayout(PipelineLayoutBase* layout) {
|
||||||
this->layout = layout;
|
mLayout = layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
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")) {
|
||||||
parentBuilder->HandleError("Currently the entry point has to be main()");
|
mParentBuilder->HandleError("Currently the entry point has to be main()");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stage != module->GetExecutionModel()) {
|
if (stage != module->GetExecutionModel()) {
|
||||||
parentBuilder->HandleError("Setting module with wrong execution model");
|
mParentBuilder->HandleError("Setting module with wrong execution model");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
nxt::ShaderStageBit bit = StageBit(stage);
|
nxt::ShaderStageBit bit = StageBit(stage);
|
||||||
if (stageMask & bit) {
|
if (mStageMask & bit) {
|
||||||
parentBuilder->HandleError("Setting already set stage");
|
mParentBuilder->HandleError("Setting already set stage");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
stageMask |= bit;
|
mStageMask |= bit;
|
||||||
|
|
||||||
stages[stage].module = module;
|
mStages[stage].module = module;
|
||||||
stages[stage].entryPoint = entryPoint;
|
mStages[stage].entryPoint = entryPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,9 +51,9 @@ namespace backend {
|
||||||
PipelineLayoutBase* GetLayout();
|
PipelineLayoutBase* GetLayout();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
nxt::ShaderStageBit stageMask;
|
nxt::ShaderStageBit mStageMask;
|
||||||
Ref<PipelineLayoutBase> layout;
|
Ref<PipelineLayoutBase> mLayout;
|
||||||
PerStage<PushConstantInfo> pushConstants;
|
PerStage<PushConstantInfo> mPushConstants;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PipelineBuilder {
|
class PipelineBuilder {
|
||||||
|
@ -74,10 +74,10 @@ namespace backend {
|
||||||
private:
|
private:
|
||||||
friend class PipelineBase;
|
friend class PipelineBase;
|
||||||
|
|
||||||
BuilderBase* parentBuilder;
|
BuilderBase* mParentBuilder;
|
||||||
Ref<PipelineLayoutBase> layout;
|
Ref<PipelineLayoutBase> mLayout;
|
||||||
nxt::ShaderStageBit stageMask;
|
nxt::ShaderStageBit mStageMask;
|
||||||
PerStage<StageInfo> stages;
|
PerStage<StageInfo> mStages;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,16 +23,16 @@ namespace backend {
|
||||||
// PipelineLayoutBase
|
// PipelineLayoutBase
|
||||||
|
|
||||||
PipelineLayoutBase::PipelineLayoutBase(PipelineLayoutBuilder* builder)
|
PipelineLayoutBase::PipelineLayoutBase(PipelineLayoutBuilder* builder)
|
||||||
: bindGroupLayouts(std::move(builder->bindGroupLayouts)), mask(builder->mask) {
|
: mBindGroupLayouts(std::move(builder->mBindGroupLayouts)), mMask(builder->mMask) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const BindGroupLayoutBase* PipelineLayoutBase::GetBindGroupLayout(size_t group) const {
|
const BindGroupLayoutBase* PipelineLayoutBase::GetBindGroupLayout(size_t group) const {
|
||||||
ASSERT(group < kMaxBindGroups);
|
ASSERT(group < kMaxBindGroups);
|
||||||
return bindGroupLayouts[group].Get();
|
return mBindGroupLayouts[group].Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::bitset<kMaxBindGroups> PipelineLayoutBase::GetBindGroupsLayoutMask() const {
|
const std::bitset<kMaxBindGroups> PipelineLayoutBase::GetBindGroupsLayoutMask() const {
|
||||||
return mask;
|
return mMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::bitset<kMaxBindGroups> PipelineLayoutBase::InheritedGroupsMask(const PipelineLayoutBase* other) const {
|
std::bitset<kMaxBindGroups> PipelineLayoutBase::InheritedGroupsMask(const PipelineLayoutBase* other) const {
|
||||||
|
@ -41,7 +41,7 @@ namespace backend {
|
||||||
|
|
||||||
uint32_t PipelineLayoutBase::GroupsInheritUpTo(const PipelineLayoutBase* other) const {
|
uint32_t PipelineLayoutBase::GroupsInheritUpTo(const PipelineLayoutBase* other) const {
|
||||||
for (uint32_t i = 0; i < kMaxBindGroups; ++i) {
|
for (uint32_t i = 0; i < kMaxBindGroups; ++i) {
|
||||||
if (!mask[i] || bindGroupLayouts[i].Get() != other->bindGroupLayouts[i].Get()) {
|
if (!mMask[i] || mBindGroupLayouts[i].Get() != other->mBindGroupLayouts[i].Get()) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,12 +57,12 @@ namespace backend {
|
||||||
// TODO(cwallez@chromium.org): this is a hack, have the null bind group layout somewhere in the device
|
// TODO(cwallez@chromium.org): this is a hack, have the null bind group layout somewhere in the device
|
||||||
// once we have a cache of BGL
|
// once we have a cache of BGL
|
||||||
for (size_t group = 0; group < kMaxBindGroups; ++group) {
|
for (size_t group = 0; group < kMaxBindGroups; ++group) {
|
||||||
if (!bindGroupLayouts[group]) {
|
if (!mBindGroupLayouts[group]) {
|
||||||
bindGroupLayouts[group] = device->CreateBindGroupLayoutBuilder()->GetResult();
|
mBindGroupLayouts[group] = mDevice->CreateBindGroupLayoutBuilder()->GetResult();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return device->CreatePipelineLayout(this);
|
return mDevice->CreatePipelineLayout(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PipelineLayoutBuilder::SetBindGroupLayout(uint32_t groupIndex, BindGroupLayoutBase* layout) {
|
void PipelineLayoutBuilder::SetBindGroupLayout(uint32_t groupIndex, BindGroupLayoutBase* layout) {
|
||||||
|
@ -70,13 +70,13 @@ namespace backend {
|
||||||
HandleError("groupIndex is over the maximum allowed");
|
HandleError("groupIndex is over the maximum allowed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (mask[groupIndex]) {
|
if (mMask[groupIndex]) {
|
||||||
HandleError("Bind group layout already specified");
|
HandleError("Bind group layout already specified");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bindGroupLayouts[groupIndex] = layout;
|
mBindGroupLayouts[groupIndex] = layout;
|
||||||
mask.set(groupIndex);
|
mMask.set(groupIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,8 +44,8 @@ namespace backend {
|
||||||
uint32_t GroupsInheritUpTo(const PipelineLayoutBase* other) const;
|
uint32_t GroupsInheritUpTo(const PipelineLayoutBase* other) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
BindGroupLayoutArray bindGroupLayouts;
|
BindGroupLayoutArray mBindGroupLayouts;
|
||||||
std::bitset<kMaxBindGroups> mask;
|
std::bitset<kMaxBindGroups> mMask;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PipelineLayoutBuilder : public Builder<PipelineLayoutBase> {
|
class PipelineLayoutBuilder : public Builder<PipelineLayoutBase> {
|
||||||
|
@ -60,8 +60,8 @@ namespace backend {
|
||||||
|
|
||||||
PipelineLayoutBase* GetResultImpl() override;
|
PipelineLayoutBase* GetResultImpl() override;
|
||||||
|
|
||||||
BindGroupLayoutArray bindGroupLayouts;
|
BindGroupLayoutArray mBindGroupLayouts;
|
||||||
std::bitset<kMaxBindGroups> mask;
|
std::bitset<kMaxBindGroups> mMask;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,11 +21,11 @@ namespace backend {
|
||||||
|
|
||||||
// QueueBase
|
// QueueBase
|
||||||
|
|
||||||
QueueBase::QueueBase(QueueBuilder* builder) : device(builder->device) {
|
QueueBase::QueueBase(QueueBuilder* builder) : mDevice(builder->mDevice) {
|
||||||
}
|
}
|
||||||
|
|
||||||
DeviceBase* QueueBase::GetDevice() {
|
DeviceBase* QueueBase::GetDevice() {
|
||||||
return device;
|
return mDevice;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QueueBase::ValidateSubmitCommand(CommandBufferBase* command) {
|
bool QueueBase::ValidateSubmitCommand(CommandBufferBase* command) {
|
||||||
|
@ -38,7 +38,7 @@ namespace backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
QueueBase* QueueBuilder::GetResultImpl() {
|
QueueBase* QueueBuilder::GetResultImpl() {
|
||||||
return device->CreateQueue(this);
|
return mDevice->CreateQueue(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ namespace backend {
|
||||||
private:
|
private:
|
||||||
bool ValidateSubmitCommand(CommandBufferBase* command);
|
bool ValidateSubmitCommand(CommandBufferBase* command);
|
||||||
|
|
||||||
DeviceBase* device;
|
DeviceBase* mDevice;
|
||||||
};
|
};
|
||||||
|
|
||||||
class QueueBuilder : public Builder<QueueBase> {
|
class QueueBuilder : public Builder<QueueBase> {
|
||||||
|
|
|
@ -25,39 +25,39 @@ namespace backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RefCounted::ReferenceInternal() {
|
void RefCounted::ReferenceInternal() {
|
||||||
ASSERT(internalRefs != 0);
|
ASSERT(mInternalRefs != 0);
|
||||||
// TODO(cwallez@chromium.org): what to do on overflow?
|
// TODO(cwallez@chromium.org): what to do on overflow?
|
||||||
internalRefs ++;
|
mInternalRefs ++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RefCounted::ReleaseInternal() {
|
void RefCounted::ReleaseInternal() {
|
||||||
ASSERT(internalRefs != 0);
|
ASSERT(mInternalRefs != 0);
|
||||||
internalRefs --;
|
mInternalRefs --;
|
||||||
if (internalRefs == 0) {
|
if (mInternalRefs == 0) {
|
||||||
ASSERT(externalRefs == 0);
|
ASSERT(mExternalRefs == 0);
|
||||||
// TODO(cwallez@chromium.org): would this work with custom allocators?
|
// TODO(cwallez@chromium.org): would this work with custom allocators?
|
||||||
delete this;
|
delete this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t RefCounted::GetExternalRefs() const {
|
uint32_t RefCounted::GetExternalRefs() const {
|
||||||
return externalRefs;
|
return mExternalRefs;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t RefCounted::GetInternalRefs() const {
|
uint32_t RefCounted::GetInternalRefs() const {
|
||||||
return internalRefs;
|
return mInternalRefs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RefCounted::Reference() {
|
void RefCounted::Reference() {
|
||||||
ASSERT(externalRefs != 0);
|
ASSERT(mExternalRefs != 0);
|
||||||
// TODO(cwallez@chromium.org): what to do on overflow?
|
// TODO(cwallez@chromium.org): what to do on overflow?
|
||||||
externalRefs ++;
|
mExternalRefs ++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RefCounted::Release() {
|
void RefCounted::Release() {
|
||||||
ASSERT(externalRefs != 0);
|
ASSERT(mExternalRefs != 0);
|
||||||
externalRefs --;
|
mExternalRefs --;
|
||||||
if (externalRefs == 0) {
|
if (mExternalRefs == 0) {
|
||||||
ReleaseInternal();
|
ReleaseInternal();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,8 +35,8 @@ namespace backend {
|
||||||
void Release();
|
void Release();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
uint32_t externalRefs = 1;
|
uint32_t mExternalRefs = 1;
|
||||||
uint32_t internalRefs = 1;
|
uint32_t mInternalRefs = 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -44,11 +44,11 @@ namespace backend {
|
||||||
public:
|
public:
|
||||||
Ref() {}
|
Ref() {}
|
||||||
|
|
||||||
Ref(T* p): pointee(p) {
|
Ref(T* p): mPointee(p) {
|
||||||
Reference();
|
Reference();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref(const Ref<T>& other): pointee(other.pointee) {
|
Ref(const Ref<T>& other): mPointee(other.mPointee) {
|
||||||
Reference();
|
Reference();
|
||||||
}
|
}
|
||||||
Ref<T>& operator=(const Ref<T>& other) {
|
Ref<T>& operator=(const Ref<T>& other) {
|
||||||
|
@ -56,69 +56,69 @@ namespace backend {
|
||||||
|
|
||||||
other.Reference();
|
other.Reference();
|
||||||
Release();
|
Release();
|
||||||
pointee = other.pointee;
|
mPointee = other.mPointee;
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref(Ref<T>&& other) {
|
Ref(Ref<T>&& other) {
|
||||||
pointee = other.pointee;
|
mPointee = other.mPointee;
|
||||||
other.pointee = nullptr;
|
other.mPointee = nullptr;
|
||||||
}
|
}
|
||||||
Ref<T>& operator=(Ref<T>&& other) {
|
Ref<T>& operator=(Ref<T>&& other) {
|
||||||
if (&other == this) return *this;
|
if (&other == this) return *this;
|
||||||
|
|
||||||
Release();
|
Release();
|
||||||
pointee = other.pointee;
|
mPointee = other.mPointee;
|
||||||
other.pointee = nullptr;
|
other.mPointee = nullptr;
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
~Ref() {
|
~Ref() {
|
||||||
Release();
|
Release();
|
||||||
pointee = nullptr;
|
mPointee = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
operator bool() {
|
operator bool() {
|
||||||
return pointee != nullptr;
|
return mPointee != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const T& operator*() const {
|
const T& operator*() const {
|
||||||
return *pointee;
|
return *mPointee;
|
||||||
}
|
}
|
||||||
T& operator*() {
|
T& operator*() {
|
||||||
return *pointee;
|
return *mPointee;
|
||||||
}
|
}
|
||||||
|
|
||||||
const T* operator->() const {
|
const T* operator->() const {
|
||||||
return pointee;
|
return mPointee;
|
||||||
}
|
}
|
||||||
T* operator->() {
|
T* operator->() {
|
||||||
return pointee;
|
return mPointee;
|
||||||
}
|
}
|
||||||
|
|
||||||
const T* Get() const {
|
const T* Get() const {
|
||||||
return pointee;
|
return mPointee;
|
||||||
}
|
}
|
||||||
T* Get() {
|
T* Get() {
|
||||||
return pointee;
|
return mPointee;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Reference() const {
|
void Reference() const {
|
||||||
if (pointee != nullptr) {
|
if (mPointee != nullptr) {
|
||||||
pointee->ReferenceInternal();
|
mPointee->ReferenceInternal();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void Release() const {
|
void Release() const {
|
||||||
if (pointee != nullptr) {
|
if (mPointee != nullptr) {
|
||||||
pointee->ReleaseInternal();
|
mPointee->ReleaseInternal();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//static_assert(std::is_base_of<RefCounted, T>::value, "");
|
//static_assert(std::is_base_of<RefCounted, T>::value, "");
|
||||||
T* pointee = nullptr;
|
T* mPointee = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,19 +25,19 @@ namespace backend {
|
||||||
// RenderPass
|
// RenderPass
|
||||||
|
|
||||||
RenderPassBase::RenderPassBase(RenderPassBuilder* builder)
|
RenderPassBase::RenderPassBase(RenderPassBuilder* builder)
|
||||||
: attachments(std::move(builder->attachments)), subpasses(std::move(builder->subpasses)) {
|
: mAttachments(std::move(builder->mAttachments)), mSubpasses(std::move(builder->mSubpasses)) {
|
||||||
for (uint32_t s = 0; s < GetSubpassCount(); ++s) {
|
for (uint32_t s = 0; s < GetSubpassCount(); ++s) {
|
||||||
const auto& subpass = GetSubpassInfo(s);
|
const auto& subpass = GetSubpassInfo(s);
|
||||||
for (auto location : IterateBitSet(subpass.colorAttachmentsSet)) {
|
for (auto location : IterateBitSet(subpass.colorAttachmentsSet)) {
|
||||||
auto attachmentSlot = subpass.colorAttachments[location];
|
auto attachmentSlot = subpass.colorAttachments[location];
|
||||||
auto& firstSubpass = attachments[attachmentSlot].firstSubpass;
|
auto& firstSubpass = mAttachments[attachmentSlot].firstSubpass;
|
||||||
if (firstSubpass == UINT32_MAX) {
|
if (firstSubpass == UINT32_MAX) {
|
||||||
firstSubpass = s;
|
firstSubpass = s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (subpass.depthStencilAttachmentSet) {
|
if (subpass.depthStencilAttachmentSet) {
|
||||||
auto attachmentSlot = subpass.depthStencilAttachment;
|
auto attachmentSlot = subpass.depthStencilAttachment;
|
||||||
auto& firstSubpass = attachments[attachmentSlot].firstSubpass;
|
auto& firstSubpass = mAttachments[attachmentSlot].firstSubpass;
|
||||||
if (firstSubpass == UINT32_MAX) {
|
if (firstSubpass == UINT32_MAX) {
|
||||||
firstSubpass = s;
|
firstSubpass = s;
|
||||||
}
|
}
|
||||||
|
@ -46,21 +46,21 @@ namespace backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t RenderPassBase::GetAttachmentCount() const {
|
uint32_t RenderPassBase::GetAttachmentCount() const {
|
||||||
return static_cast<uint32_t>(attachments.size());
|
return static_cast<uint32_t>(mAttachments.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
const RenderPassBase::AttachmentInfo& RenderPassBase::GetAttachmentInfo(uint32_t attachment) const {
|
const RenderPassBase::AttachmentInfo& RenderPassBase::GetAttachmentInfo(uint32_t attachment) const {
|
||||||
ASSERT(attachment < attachments.size());
|
ASSERT(attachment < mAttachments.size());
|
||||||
return attachments[attachment];
|
return mAttachments[attachment];
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t RenderPassBase::GetSubpassCount() const {
|
uint32_t RenderPassBase::GetSubpassCount() const {
|
||||||
return static_cast<uint32_t>(subpasses.size());
|
return static_cast<uint32_t>(mSubpasses.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
const RenderPassBase::SubpassInfo& RenderPassBase::GetSubpassInfo(uint32_t subpass) const {
|
const RenderPassBase::SubpassInfo& RenderPassBase::GetSubpassInfo(uint32_t subpass) const {
|
||||||
ASSERT(subpass < subpasses.size());
|
ASSERT(subpass < mSubpasses.size());
|
||||||
return subpasses[subpass];
|
return mSubpasses[subpass];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RenderPassBase::IsCompatibleWith(const RenderPassBase* other) const {
|
bool RenderPassBase::IsCompatibleWith(const RenderPassBase* other) const {
|
||||||
|
@ -77,102 +77,102 @@ namespace backend {
|
||||||
};
|
};
|
||||||
|
|
||||||
RenderPassBuilder::RenderPassBuilder(DeviceBase* device)
|
RenderPassBuilder::RenderPassBuilder(DeviceBase* device)
|
||||||
: Builder(device), subpasses(1) {
|
: Builder(device), mSubpasses(1) {
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderPassBase* RenderPassBuilder::GetResultImpl() {
|
RenderPassBase* RenderPassBuilder::GetResultImpl() {
|
||||||
constexpr int requiredProperties = RENDERPASS_PROPERTY_ATTACHMENT_COUNT | RENDERPASS_PROPERTY_SUBPASS_COUNT;
|
constexpr int requiredProperties = RENDERPASS_PROPERTY_ATTACHMENT_COUNT | RENDERPASS_PROPERTY_SUBPASS_COUNT;
|
||||||
if ((propertiesSet & requiredProperties) != requiredProperties) {
|
if ((mPropertiesSet & requiredProperties) != requiredProperties) {
|
||||||
HandleError("Render pass missing properties");
|
HandleError("Render pass missing properties");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& prop : attachmentProperties) {
|
for (const auto& prop : mAttachmentProperties) {
|
||||||
if (!prop.all()) {
|
if (!prop.all()) {
|
||||||
HandleError("A render pass attachment is missing some property");
|
HandleError("A render pass attachment is missing some property");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& subpass : subpasses) {
|
for (const auto& subpass : mSubpasses) {
|
||||||
for (unsigned int location : IterateBitSet(subpass.colorAttachmentsSet)) {
|
for (unsigned int location : IterateBitSet(subpass.colorAttachmentsSet)) {
|
||||||
uint32_t slot = subpass.colorAttachments[location];
|
uint32_t slot = subpass.colorAttachments[location];
|
||||||
if (TextureFormatHasDepthOrStencil(attachments[slot].format)) {
|
if (TextureFormatHasDepthOrStencil(mAttachments[slot].format)) {
|
||||||
HandleError("Render pass color attachment is not of a color format");
|
HandleError("Render pass color attachment is not of a color format");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (subpass.depthStencilAttachmentSet) {
|
if (subpass.depthStencilAttachmentSet) {
|
||||||
uint32_t slot = subpass.depthStencilAttachment;
|
uint32_t slot = subpass.depthStencilAttachment;
|
||||||
if (!TextureFormatHasDepthOrStencil(attachments[slot].format)) {
|
if (!TextureFormatHasDepthOrStencil(mAttachments[slot].format)) {
|
||||||
HandleError("Render pass depth/stencil attachment is not of a depth/stencil format");
|
HandleError("Render pass depth/stencil attachment is not of a depth/stencil format");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return device->CreateRenderPass(this);
|
return mDevice->CreateRenderPass(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderPassBuilder::SetAttachmentCount(uint32_t attachmentCount) {
|
void RenderPassBuilder::SetAttachmentCount(uint32_t attachmentCount) {
|
||||||
if ((propertiesSet & RENDERPASS_PROPERTY_ATTACHMENT_COUNT) != 0) {
|
if ((mPropertiesSet & RENDERPASS_PROPERTY_ATTACHMENT_COUNT) != 0) {
|
||||||
HandleError("Render pass attachment count property set multiple times");
|
HandleError("Render pass attachment count property set multiple times");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
attachmentProperties.resize(attachmentCount);
|
mAttachmentProperties.resize(attachmentCount);
|
||||||
attachments.resize(attachmentCount);
|
mAttachments.resize(attachmentCount);
|
||||||
propertiesSet |= RENDERPASS_PROPERTY_ATTACHMENT_COUNT;
|
mPropertiesSet |= RENDERPASS_PROPERTY_ATTACHMENT_COUNT;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderPassBuilder::AttachmentSetFormat(uint32_t attachmentSlot, nxt::TextureFormat format) {
|
void RenderPassBuilder::AttachmentSetFormat(uint32_t attachmentSlot, nxt::TextureFormat format) {
|
||||||
if ((propertiesSet & RENDERPASS_PROPERTY_ATTACHMENT_COUNT) == 0) {
|
if ((mPropertiesSet & RENDERPASS_PROPERTY_ATTACHMENT_COUNT) == 0) {
|
||||||
HandleError("Render pass attachment count not set yet");
|
HandleError("Render pass attachment count not set yet");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (attachmentSlot >= attachments.size()) {
|
if (attachmentSlot >= mAttachments.size()) {
|
||||||
HandleError("Render pass attachment slot out of bounds");
|
HandleError("Render pass attachment slot out of bounds");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (attachmentProperties[attachmentSlot][ATTACHMENT_PROPERTY_FORMAT]) {
|
if (mAttachmentProperties[attachmentSlot][ATTACHMENT_PROPERTY_FORMAT]) {
|
||||||
HandleError("Render pass attachment format already set");
|
HandleError("Render pass attachment format already set");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
attachments[attachmentSlot].format = format;
|
mAttachments[attachmentSlot].format = format;
|
||||||
attachmentProperties[attachmentSlot].set(ATTACHMENT_PROPERTY_FORMAT);
|
mAttachmentProperties[attachmentSlot].set(ATTACHMENT_PROPERTY_FORMAT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderPassBuilder::AttachmentSetColorLoadOp(uint32_t attachmentSlot, nxt::LoadOp op) {
|
void RenderPassBuilder::AttachmentSetColorLoadOp(uint32_t attachmentSlot, nxt::LoadOp op) {
|
||||||
if ((propertiesSet & RENDERPASS_PROPERTY_ATTACHMENT_COUNT) == 0) {
|
if ((mPropertiesSet & RENDERPASS_PROPERTY_ATTACHMENT_COUNT) == 0) {
|
||||||
HandleError("Render pass attachment count not set yet");
|
HandleError("Render pass attachment count not set yet");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (attachmentSlot >= attachments.size()) {
|
if (attachmentSlot >= mAttachments.size()) {
|
||||||
HandleError("Render pass attachment slot out of bounds");
|
HandleError("Render pass attachment slot out of bounds");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
attachments[attachmentSlot].colorLoadOp = op;
|
mAttachments[attachmentSlot].colorLoadOp = op;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderPassBuilder::AttachmentSetDepthStencilLoadOps(uint32_t attachmentSlot, nxt::LoadOp depthOp, nxt::LoadOp stencilOp) {
|
void RenderPassBuilder::AttachmentSetDepthStencilLoadOps(uint32_t attachmentSlot, nxt::LoadOp depthOp, nxt::LoadOp stencilOp) {
|
||||||
if ((propertiesSet & RENDERPASS_PROPERTY_ATTACHMENT_COUNT) == 0) {
|
if ((mPropertiesSet & RENDERPASS_PROPERTY_ATTACHMENT_COUNT) == 0) {
|
||||||
HandleError("Render pass attachment count not set yet");
|
HandleError("Render pass attachment count not set yet");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (attachmentSlot >= attachments.size()) {
|
if (attachmentSlot >= mAttachments.size()) {
|
||||||
HandleError("Render pass attachment slot out of bounds");
|
HandleError("Render pass attachment slot out of bounds");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
attachments[attachmentSlot].depthLoadOp = depthOp;
|
mAttachments[attachmentSlot].depthLoadOp = depthOp;
|
||||||
attachments[attachmentSlot].stencilLoadOp = stencilOp;
|
mAttachments[attachmentSlot].stencilLoadOp = stencilOp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RenderPassBuilder::SetSubpassCount(uint32_t subpassCount) {
|
void RenderPassBuilder::SetSubpassCount(uint32_t subpassCount) {
|
||||||
if ((propertiesSet & RENDERPASS_PROPERTY_SUBPASS_COUNT) != 0) {
|
if ((mPropertiesSet & RENDERPASS_PROPERTY_SUBPASS_COUNT) != 0) {
|
||||||
HandleError("Render pass subpass count property set multiple times");
|
HandleError("Render pass subpass count property set multiple times");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -181,20 +181,20 @@ namespace backend {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
subpasses.resize(subpassCount);
|
mSubpasses.resize(subpassCount);
|
||||||
propertiesSet |= RENDERPASS_PROPERTY_SUBPASS_COUNT;
|
mPropertiesSet |= RENDERPASS_PROPERTY_SUBPASS_COUNT;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderPassBuilder::SubpassSetColorAttachment(uint32_t subpass, uint32_t outputAttachmentLocation, uint32_t attachmentSlot) {
|
void RenderPassBuilder::SubpassSetColorAttachment(uint32_t subpass, uint32_t outputAttachmentLocation, uint32_t attachmentSlot) {
|
||||||
if ((propertiesSet & RENDERPASS_PROPERTY_SUBPASS_COUNT) == 0) {
|
if ((mPropertiesSet & RENDERPASS_PROPERTY_SUBPASS_COUNT) == 0) {
|
||||||
HandleError("Render pass subpass count not set yet");
|
HandleError("Render pass subpass count not set yet");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ((propertiesSet & RENDERPASS_PROPERTY_ATTACHMENT_COUNT) == 0) {
|
if ((mPropertiesSet & RENDERPASS_PROPERTY_ATTACHMENT_COUNT) == 0) {
|
||||||
HandleError("Render pass attachment count not set yet");
|
HandleError("Render pass attachment count not set yet");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (subpass >= subpasses.size()) {
|
if (subpass >= mSubpasses.size()) {
|
||||||
HandleError("Subpass index out of bounds");
|
HandleError("Subpass index out of bounds");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -202,43 +202,43 @@ namespace backend {
|
||||||
HandleError("Subpass output attachment location out of bounds");
|
HandleError("Subpass output attachment location out of bounds");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (attachmentSlot >= attachments.size()) {
|
if (attachmentSlot >= mAttachments.size()) {
|
||||||
HandleError("Subpass attachment slot out of bounds");
|
HandleError("Subpass attachment slot out of bounds");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (subpasses[subpass].colorAttachmentsSet[outputAttachmentLocation]) {
|
if (mSubpasses[subpass].colorAttachmentsSet[outputAttachmentLocation]) {
|
||||||
HandleError("Subpass color attachment already set");
|
HandleError("Subpass color attachment already set");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
subpasses[subpass].colorAttachmentsSet.set(outputAttachmentLocation);
|
mSubpasses[subpass].colorAttachmentsSet.set(outputAttachmentLocation);
|
||||||
subpasses[subpass].colorAttachments[outputAttachmentLocation] = attachmentSlot;
|
mSubpasses[subpass].colorAttachments[outputAttachmentLocation] = attachmentSlot;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderPassBuilder::SubpassSetDepthStencilAttachment(uint32_t subpass, uint32_t attachmentSlot) {
|
void RenderPassBuilder::SubpassSetDepthStencilAttachment(uint32_t subpass, uint32_t attachmentSlot) {
|
||||||
if ((propertiesSet & RENDERPASS_PROPERTY_SUBPASS_COUNT) == 0) {
|
if ((mPropertiesSet & RENDERPASS_PROPERTY_SUBPASS_COUNT) == 0) {
|
||||||
HandleError("Render pass subpass count not set yet");
|
HandleError("Render pass subpass count not set yet");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ((propertiesSet & RENDERPASS_PROPERTY_ATTACHMENT_COUNT) == 0) {
|
if ((mPropertiesSet & RENDERPASS_PROPERTY_ATTACHMENT_COUNT) == 0) {
|
||||||
HandleError("Render pass attachment count not set yet");
|
HandleError("Render pass attachment count not set yet");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (subpass >= subpasses.size()) {
|
if (subpass >= mSubpasses.size()) {
|
||||||
HandleError("Subpass index out of bounds");
|
HandleError("Subpass index out of bounds");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (attachmentSlot >= attachments.size()) {
|
if (attachmentSlot >= mAttachments.size()) {
|
||||||
HandleError("Subpass attachment slot out of bounds");
|
HandleError("Subpass attachment slot out of bounds");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (subpasses[subpass].depthStencilAttachmentSet) {
|
if (mSubpasses[subpass].depthStencilAttachmentSet) {
|
||||||
HandleError("Subpass depth-stencil attachment already set");
|
HandleError("Subpass depth-stencil attachment already set");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
subpasses[subpass].depthStencilAttachmentSet = true;
|
mSubpasses[subpass].depthStencilAttachmentSet = true;
|
||||||
subpasses[subpass].depthStencilAttachment = attachmentSlot;
|
mSubpasses[subpass].depthStencilAttachment = attachmentSlot;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,8 +59,8 @@ namespace backend {
|
||||||
bool IsCompatibleWith(const RenderPassBase* other) const;
|
bool IsCompatibleWith(const RenderPassBase* other) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<AttachmentInfo> attachments;
|
std::vector<AttachmentInfo> mAttachments;
|
||||||
std::vector<SubpassInfo> subpasses;
|
std::vector<SubpassInfo> mSubpasses;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RenderPassBuilder : public Builder<RenderPassBase> {
|
class RenderPassBuilder : public Builder<RenderPassBase> {
|
||||||
|
@ -85,10 +85,10 @@ namespace backend {
|
||||||
ATTACHMENT_PROPERTY_COUNT
|
ATTACHMENT_PROPERTY_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<std::bitset<ATTACHMENT_PROPERTY_COUNT>> attachmentProperties;
|
std::vector<std::bitset<ATTACHMENT_PROPERTY_COUNT>> mAttachmentProperties;
|
||||||
std::vector<RenderPassBase::AttachmentInfo> attachments;
|
std::vector<RenderPassBase::AttachmentInfo> mAttachments;
|
||||||
std::vector<RenderPassBase::SubpassInfo> subpasses;
|
std::vector<RenderPassBase::SubpassInfo> mSubpasses;
|
||||||
int propertiesSet = 0;
|
int mPropertiesSet = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,12 +27,12 @@ namespace backend {
|
||||||
|
|
||||||
RenderPipelineBase::RenderPipelineBase(RenderPipelineBuilder* builder)
|
RenderPipelineBase::RenderPipelineBase(RenderPipelineBuilder* builder)
|
||||||
: PipelineBase(builder),
|
: PipelineBase(builder),
|
||||||
depthStencilState(std::move(builder->depthStencilState)),
|
mDepthStencilState(std::move(builder->mDepthStencilState)),
|
||||||
indexFormat(builder->indexFormat),
|
mIndexFormat(builder->mIndexFormat),
|
||||||
inputState(std::move(builder->inputState)),
|
mInputState(std::move(builder->mInputState)),
|
||||||
primitiveTopology(builder->primitiveTopology),
|
mPrimitiveTopology(builder->mPrimitiveTopology),
|
||||||
blendStates(builder->blendStates),
|
mBlendStates(builder->mBlendStates),
|
||||||
renderPass(std::move(builder->renderPass)), subpass(builder->subpass) {
|
mRenderPass(std::move(builder->mRenderPass)), mSubpass(builder->mSubpass) {
|
||||||
|
|
||||||
if (GetStageMask() != (nxt::ShaderStageBit::Vertex | nxt::ShaderStageBit::Fragment)) {
|
if (GetStageMask() != (nxt::ShaderStageBit::Vertex | nxt::ShaderStageBit::Fragment)) {
|
||||||
builder->HandleError("Render pipeline should have exactly a vertex and fragment stage");
|
builder->HandleError("Render pipeline should have exactly a vertex and fragment stage");
|
||||||
|
@ -41,39 +41,39 @@ namespace backend {
|
||||||
|
|
||||||
// TODO(kainino@chromium.org): Need to verify the pipeline against its render subpass.
|
// TODO(kainino@chromium.org): Need to verify the pipeline against its render subpass.
|
||||||
|
|
||||||
if ((builder->GetStageInfo(nxt::ShaderStage::Vertex).module->GetUsedVertexAttributes() & ~inputState->GetAttributesSetMask()).any()) {
|
if ((builder->GetStageInfo(nxt::ShaderStage::Vertex).module->GetUsedVertexAttributes() & ~mInputState->GetAttributesSetMask()).any()) {
|
||||||
builder->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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BlendStateBase* RenderPipelineBase::GetBlendState(uint32_t attachmentSlot) {
|
BlendStateBase* RenderPipelineBase::GetBlendState(uint32_t attachmentSlot) {
|
||||||
ASSERT(attachmentSlot < blendStates.size());
|
ASSERT(attachmentSlot < mBlendStates.size());
|
||||||
return blendStates[attachmentSlot].Get();
|
return mBlendStates[attachmentSlot].Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
DepthStencilStateBase* RenderPipelineBase::GetDepthStencilState() {
|
DepthStencilStateBase* RenderPipelineBase::GetDepthStencilState() {
|
||||||
return depthStencilState.Get();
|
return mDepthStencilState.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
nxt::IndexFormat RenderPipelineBase::GetIndexFormat() const {
|
nxt::IndexFormat RenderPipelineBase::GetIndexFormat() const {
|
||||||
return indexFormat;
|
return mIndexFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
InputStateBase* RenderPipelineBase::GetInputState() {
|
InputStateBase* RenderPipelineBase::GetInputState() {
|
||||||
return inputState.Get();
|
return mInputState.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
nxt::PrimitiveTopology RenderPipelineBase::GetPrimitiveTopology() const {
|
nxt::PrimitiveTopology RenderPipelineBase::GetPrimitiveTopology() const {
|
||||||
return primitiveTopology;
|
return mPrimitiveTopology;
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderPassBase* RenderPipelineBase::GetRenderPass() {
|
RenderPassBase* RenderPipelineBase::GetRenderPass() {
|
||||||
return renderPass.Get();
|
return mRenderPass.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t RenderPipelineBase::GetSubPass() {
|
uint32_t RenderPipelineBase::GetSubPass() {
|
||||||
return subpass;
|
return mSubpass;
|
||||||
}
|
}
|
||||||
|
|
||||||
// RenderPipelineBuilder
|
// RenderPipelineBuilder
|
||||||
|
@ -84,64 +84,64 @@ namespace backend {
|
||||||
|
|
||||||
RenderPipelineBase* RenderPipelineBuilder::GetResultImpl() {
|
RenderPipelineBase* RenderPipelineBuilder::GetResultImpl() {
|
||||||
// TODO(cwallez@chromium.org): the layout should be required, and put the default objects in the device
|
// TODO(cwallez@chromium.org): the layout should be required, and put the default objects in the device
|
||||||
if (!inputState) {
|
if (!mInputState) {
|
||||||
inputState = device->CreateInputStateBuilder()->GetResult();
|
mInputState = mDevice->CreateInputStateBuilder()->GetResult();
|
||||||
}
|
}
|
||||||
if (!depthStencilState) {
|
if (!mDepthStencilState) {
|
||||||
depthStencilState = device->CreateDepthStencilStateBuilder()->GetResult();
|
mDepthStencilState = mDevice->CreateDepthStencilStateBuilder()->GetResult();
|
||||||
}
|
}
|
||||||
if (!renderPass) {
|
if (!mRenderPass) {
|
||||||
HandleError("Pipeline render pass not set");
|
HandleError("Pipeline render pass not set");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
const auto& subpassInfo = renderPass->GetSubpassInfo(subpass);
|
const auto& subpassInfo = mRenderPass->GetSubpassInfo(mSubpass);
|
||||||
if ((blendStatesSet | subpassInfo.colorAttachmentsSet) != subpassInfo.colorAttachmentsSet) {
|
if ((mBlendStatesSet | subpassInfo.colorAttachmentsSet) != subpassInfo.colorAttachmentsSet) {
|
||||||
HandleError("Blend state set on unset color attachment");
|
HandleError("Blend state set on unset color attachment");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assign all color attachments without a blend state the default state
|
// Assign all color attachments without a blend state the default state
|
||||||
// TODO(enga@google.com): Put the default objects in the device
|
// TODO(enga@google.com): Put the default objects in the device
|
||||||
for (uint32_t attachmentSlot : IterateBitSet(subpassInfo.colorAttachmentsSet & ~blendStatesSet)) {
|
for (uint32_t attachmentSlot : IterateBitSet(subpassInfo.colorAttachmentsSet & ~mBlendStatesSet)) {
|
||||||
blendStates[attachmentSlot] = device->CreateBlendStateBuilder()->GetResult();
|
mBlendStates[attachmentSlot] = mDevice->CreateBlendStateBuilder()->GetResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
return device->CreateRenderPipeline(this);
|
return mDevice->CreateRenderPipeline(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderPipelineBuilder::SetColorAttachmentBlendState(uint32_t attachmentSlot, BlendStateBase* blendState) {
|
void RenderPipelineBuilder::SetColorAttachmentBlendState(uint32_t attachmentSlot, BlendStateBase* blendState) {
|
||||||
if (attachmentSlot > blendStates.size()) {
|
if (attachmentSlot > mBlendStates.size()) {
|
||||||
HandleError("Attachment index out of bounds");
|
HandleError("Attachment index out of bounds");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (blendStatesSet[attachmentSlot]) {
|
if (mBlendStatesSet[attachmentSlot]) {
|
||||||
HandleError("Attachment blend state already set");
|
HandleError("Attachment blend state already set");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
blendStatesSet.set(attachmentSlot);
|
mBlendStatesSet.set(attachmentSlot);
|
||||||
blendStates[attachmentSlot] = blendState;
|
mBlendStates[attachmentSlot] = blendState;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderPipelineBuilder::SetDepthStencilState(DepthStencilStateBase* depthStencilState) {
|
void RenderPipelineBuilder::SetDepthStencilState(DepthStencilStateBase* depthStencilState) {
|
||||||
this->depthStencilState = depthStencilState;
|
mDepthStencilState = depthStencilState;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderPipelineBuilder::SetIndexFormat(nxt::IndexFormat format) {
|
void RenderPipelineBuilder::SetIndexFormat(nxt::IndexFormat format) {
|
||||||
this->indexFormat = format;
|
mIndexFormat = format;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderPipelineBuilder::SetInputState(InputStateBase* inputState) {
|
void RenderPipelineBuilder::SetInputState(InputStateBase* inputState) {
|
||||||
this->inputState = inputState;
|
mInputState = inputState;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderPipelineBuilder::SetPrimitiveTopology(nxt::PrimitiveTopology primitiveTopology) {
|
void RenderPipelineBuilder::SetPrimitiveTopology(nxt::PrimitiveTopology primitiveTopology) {
|
||||||
this->primitiveTopology = primitiveTopology;
|
mPrimitiveTopology = primitiveTopology;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderPipelineBuilder::SetSubpass(RenderPassBase* renderPass, uint32_t subpass) {
|
void RenderPipelineBuilder::SetSubpass(RenderPassBase* renderPass, uint32_t subpass) {
|
||||||
this->renderPass = renderPass;
|
mRenderPass = renderPass;
|
||||||
this->subpass = subpass;
|
mSubpass = subpass;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,13 +37,13 @@ namespace backend {
|
||||||
uint32_t GetSubPass();
|
uint32_t GetSubPass();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ref<DepthStencilStateBase> depthStencilState;
|
Ref<DepthStencilStateBase> mDepthStencilState;
|
||||||
nxt::IndexFormat indexFormat;
|
nxt::IndexFormat mIndexFormat;
|
||||||
Ref<InputStateBase> inputState;
|
Ref<InputStateBase> mInputState;
|
||||||
nxt::PrimitiveTopology primitiveTopology;
|
nxt::PrimitiveTopology mPrimitiveTopology;
|
||||||
std::array<Ref<BlendStateBase>, kMaxColorAttachments> blendStates;
|
std::array<Ref<BlendStateBase>, kMaxColorAttachments> mBlendStates;
|
||||||
Ref<RenderPassBase> renderPass;
|
Ref<RenderPassBase> mRenderPass;
|
||||||
uint32_t subpass;
|
uint32_t mSubpass;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RenderPipelineBuilder : public Builder<RenderPipelineBase>, public PipelineBuilder {
|
class RenderPipelineBuilder : public Builder<RenderPipelineBase>, public PipelineBuilder {
|
||||||
|
@ -63,15 +63,15 @@ namespace backend {
|
||||||
|
|
||||||
RenderPipelineBase* GetResultImpl() override;
|
RenderPipelineBase* GetResultImpl() override;
|
||||||
|
|
||||||
Ref<DepthStencilStateBase> depthStencilState;
|
Ref<DepthStencilStateBase> mDepthStencilState;
|
||||||
Ref<InputStateBase> inputState;
|
Ref<InputStateBase> mInputState;
|
||||||
// TODO(enga@google.com): Remove default when we validate that all required properties are set
|
// TODO(enga@google.com): Remove default when we validate that all required properties are set
|
||||||
nxt::PrimitiveTopology primitiveTopology = nxt::PrimitiveTopology::TriangleList;
|
nxt::PrimitiveTopology mPrimitiveTopology = nxt::PrimitiveTopology::TriangleList;
|
||||||
nxt::IndexFormat indexFormat = nxt::IndexFormat::Uint32;
|
nxt::IndexFormat mIndexFormat = nxt::IndexFormat::Uint32;
|
||||||
std::bitset<kMaxColorAttachments> blendStatesSet;
|
std::bitset<kMaxColorAttachments> mBlendStatesSet;
|
||||||
std::array<Ref<BlendStateBase>, kMaxColorAttachments> blendStates;
|
std::array<Ref<BlendStateBase>, kMaxColorAttachments> mBlendStates;
|
||||||
Ref<RenderPassBase> renderPass;
|
Ref<RenderPassBase> mRenderPass;
|
||||||
uint32_t subpass;
|
uint32_t mSubpass;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,31 +32,31 @@ namespace backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
nxt::FilterMode SamplerBuilder::GetMagFilter() const {
|
nxt::FilterMode SamplerBuilder::GetMagFilter() const {
|
||||||
return magFilter;
|
return mMagFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
nxt::FilterMode SamplerBuilder::GetMinFilter() const {
|
nxt::FilterMode SamplerBuilder::GetMinFilter() const {
|
||||||
return minFilter;
|
return mMinFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
nxt::FilterMode SamplerBuilder::GetMipMapFilter() const {
|
nxt::FilterMode SamplerBuilder::GetMipMapFilter() const {
|
||||||
return mipMapFilter;
|
return mMipMapFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
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 ((mPropertiesSet & SAMPLER_PROPERTY_FILTER) != 0) {
|
||||||
HandleError("Sampler filter property set multiple times");
|
HandleError("Sampler filter property set multiple times");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->magFilter = magFilter;
|
mMagFilter = magFilter;
|
||||||
this->minFilter = minFilter;
|
mMinFilter = minFilter;
|
||||||
this->mipMapFilter = mipMapFilter;
|
mMipMapFilter = mipMapFilter;
|
||||||
propertiesSet |= SAMPLER_PROPERTY_FILTER;
|
mPropertiesSet |= SAMPLER_PROPERTY_FILTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
SamplerBase* SamplerBuilder::GetResultImpl() {
|
SamplerBase* SamplerBuilder::GetResultImpl() {
|
||||||
return device->CreateSampler(this);
|
return mDevice->CreateSampler(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,11 +44,11 @@ namespace backend {
|
||||||
|
|
||||||
SamplerBase* GetResultImpl() override;
|
SamplerBase* GetResultImpl() override;
|
||||||
|
|
||||||
int propertiesSet = 0;
|
int mPropertiesSet = 0;
|
||||||
|
|
||||||
nxt::FilterMode magFilter = nxt::FilterMode::Nearest;
|
nxt::FilterMode mMagFilter = nxt::FilterMode::Nearest;
|
||||||
nxt::FilterMode minFilter = nxt::FilterMode::Nearest;
|
nxt::FilterMode mMinFilter = nxt::FilterMode::Nearest;
|
||||||
nxt::FilterMode mipMapFilter = nxt::FilterMode::Nearest;
|
nxt::FilterMode mMipMapFilter = nxt::FilterMode::Nearest;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,11 +24,11 @@
|
||||||
namespace backend {
|
namespace backend {
|
||||||
|
|
||||||
ShaderModuleBase::ShaderModuleBase(ShaderModuleBuilder* builder)
|
ShaderModuleBase::ShaderModuleBase(ShaderModuleBuilder* builder)
|
||||||
: device(builder->device) {
|
: mDevice(builder->mDevice) {
|
||||||
}
|
}
|
||||||
|
|
||||||
DeviceBase* ShaderModuleBase::GetDevice() const {
|
DeviceBase* ShaderModuleBase::GetDevice() const {
|
||||||
return device;
|
return mDevice;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShaderModuleBase::ExtractSpirvInfo(const spirv_cross::Compiler& compiler) {
|
void ShaderModuleBase::ExtractSpirvInfo(const spirv_cross::Compiler& compiler) {
|
||||||
|
@ -38,22 +38,22 @@ namespace backend {
|
||||||
|
|
||||||
switch (compiler.get_execution_model()) {
|
switch (compiler.get_execution_model()) {
|
||||||
case spv::ExecutionModelVertex:
|
case spv::ExecutionModelVertex:
|
||||||
executionModel = nxt::ShaderStage::Vertex;
|
mExecutionModel = nxt::ShaderStage::Vertex;
|
||||||
break;
|
break;
|
||||||
case spv::ExecutionModelFragment:
|
case spv::ExecutionModelFragment:
|
||||||
executionModel = nxt::ShaderStage::Fragment;
|
mExecutionModel = nxt::ShaderStage::Fragment;
|
||||||
break;
|
break;
|
||||||
case spv::ExecutionModelGLCompute:
|
case spv::ExecutionModelGLCompute:
|
||||||
executionModel = nxt::ShaderStage::Compute;
|
mExecutionModel = nxt::ShaderStage::Compute;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract push constants
|
// Extract push constants
|
||||||
pushConstants.mask.reset();
|
mPushConstants.mask.reset();
|
||||||
pushConstants.sizes.fill(0);
|
mPushConstants.sizes.fill(0);
|
||||||
pushConstants.types.fill(PushConstantType::Int);
|
mPushConstants.types.fill(PushConstantType::Int);
|
||||||
|
|
||||||
if (resources.push_constant_buffers.size() > 0) {
|
if (resources.push_constant_buffers.size() > 0) {
|
||||||
auto interfaceBlock = resources.push_constant_buffers[0];
|
auto interfaceBlock = resources.push_constant_buffers[0];
|
||||||
|
@ -87,14 +87,14 @@ namespace backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offset + size > kMaxPushConstants) {
|
if (offset + size > kMaxPushConstants) {
|
||||||
device->HandleError("Push constant block too big in the SPIRV");
|
mDevice->HandleError("Push constant block too big in the SPIRV");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pushConstants.mask.set(offset);
|
mPushConstants.mask.set(offset);
|
||||||
pushConstants.names[offset] = interfaceBlock.name + "." + compiler.get_member_name(blockType.self, i);
|
mPushConstants.names[offset] = interfaceBlock.name + "." + compiler.get_member_name(blockType.self, i);
|
||||||
pushConstants.sizes[offset] = size;
|
mPushConstants.sizes[offset] = size;
|
||||||
pushConstants.types[offset] = constantType;
|
mPushConstants.types[offset] = constantType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,11 +109,11 @@ namespace backend {
|
||||||
uint32_t set = compiler.get_decoration(resource.id, spv::DecorationDescriptorSet);
|
uint32_t set = compiler.get_decoration(resource.id, spv::DecorationDescriptorSet);
|
||||||
|
|
||||||
if (binding >= kMaxBindingsPerGroup || set >= kMaxBindGroups) {
|
if (binding >= kMaxBindingsPerGroup || set >= kMaxBindGroups) {
|
||||||
device->HandleError("Binding over limits in the SPIRV");
|
mDevice->HandleError("Binding over limits in the SPIRV");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& info = bindingInfo[set][binding];
|
auto& info = mBindingInfo[set][binding];
|
||||||
info.used = true;
|
info.used = true;
|
||||||
info.id = resource.id;
|
info.id = resource.id;
|
||||||
info.base_type_id = resource.base_type_id;
|
info.base_type_id = resource.base_type_id;
|
||||||
|
@ -127,35 +127,35 @@ namespace backend {
|
||||||
ExtractResourcesBinding(resources.storage_buffers, compiler, nxt::BindingType::StorageBuffer);
|
ExtractResourcesBinding(resources.storage_buffers, compiler, nxt::BindingType::StorageBuffer);
|
||||||
|
|
||||||
// Extract the vertex attributes
|
// Extract the vertex attributes
|
||||||
if (executionModel == nxt::ShaderStage::Vertex) {
|
if (mExecutionModel == nxt::ShaderStage::Vertex) {
|
||||||
for (const auto& attrib : resources.stage_inputs) {
|
for (const auto& attrib : resources.stage_inputs) {
|
||||||
ASSERT(compiler.get_decoration_mask(attrib.id) & (1ull << spv::DecorationLocation));
|
ASSERT(compiler.get_decoration_mask(attrib.id) & (1ull << spv::DecorationLocation));
|
||||||
uint32_t location = compiler.get_decoration(attrib.id, spv::DecorationLocation);
|
uint32_t location = compiler.get_decoration(attrib.id, spv::DecorationLocation);
|
||||||
|
|
||||||
if (location >= kMaxVertexAttributes) {
|
if (location >= kMaxVertexAttributes) {
|
||||||
device->HandleError("Attribute location over limits in the SPIRV");
|
mDevice->HandleError("Attribute location over limits in the SPIRV");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
usedVertexAttributes.set(location);
|
mUsedVertexAttributes.set(location);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Without a location qualifier on vertex outputs, spirv_cross::CompilerMSL gives them all
|
// Without a location qualifier on vertex outputs, spirv_cross::CompilerMSL gives them all
|
||||||
// the location 0, causing a compile error.
|
// the location 0, causing a compile error.
|
||||||
for (const auto& attrib : resources.stage_outputs) {
|
for (const auto& attrib : resources.stage_outputs) {
|
||||||
if (!(compiler.get_decoration_mask(attrib.id) & (1ull << spv::DecorationLocation))) {
|
if (!(compiler.get_decoration_mask(attrib.id) & (1ull << spv::DecorationLocation))) {
|
||||||
device->HandleError("Need location qualifier on vertex output");
|
mDevice->HandleError("Need location qualifier on vertex output");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (executionModel == nxt::ShaderStage::Fragment) {
|
if (mExecutionModel == nxt::ShaderStage::Fragment) {
|
||||||
// Without a location qualifier on vertex inputs, spirv_cross::CompilerMSL gives them all
|
// Without a location qualifier on vertex inputs, spirv_cross::CompilerMSL gives them all
|
||||||
// the location 0, causing a compile error.
|
// the location 0, causing a compile error.
|
||||||
for (const auto& attrib : resources.stage_inputs) {
|
for (const auto& attrib : resources.stage_inputs) {
|
||||||
if (!(compiler.get_decoration_mask(attrib.id) & (1ull << spv::DecorationLocation))) {
|
if (!(compiler.get_decoration_mask(attrib.id) & (1ull << spv::DecorationLocation))) {
|
||||||
device->HandleError("Need location qualifier on fragment input");
|
mDevice->HandleError("Need location qualifier on fragment input");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -163,19 +163,19 @@ namespace backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
const ShaderModuleBase::PushConstantInfo& ShaderModuleBase::GetPushConstants() const {
|
const ShaderModuleBase::PushConstantInfo& ShaderModuleBase::GetPushConstants() const {
|
||||||
return pushConstants;
|
return mPushConstants;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ShaderModuleBase::ModuleBindingInfo& ShaderModuleBase::GetBindingInfo() const {
|
const ShaderModuleBase::ModuleBindingInfo& ShaderModuleBase::GetBindingInfo() const {
|
||||||
return bindingInfo;
|
return mBindingInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::bitset<kMaxVertexAttributes>& ShaderModuleBase::GetUsedVertexAttributes() const {
|
const std::bitset<kMaxVertexAttributes>& ShaderModuleBase::GetUsedVertexAttributes() const {
|
||||||
return usedVertexAttributes;
|
return mUsedVertexAttributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
nxt::ShaderStage ShaderModuleBase::GetExecutionModel() const {
|
nxt::ShaderStage ShaderModuleBase::GetExecutionModel() const {
|
||||||
return executionModel;
|
return mExecutionModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ShaderModuleBase::IsCompatibleWithPipelineLayout(const PipelineLayoutBase* layout) {
|
bool ShaderModuleBase::IsCompatibleWithPipelineLayout(const PipelineLayoutBase* layout) {
|
||||||
|
@ -190,7 +190,7 @@ namespace backend {
|
||||||
bool ShaderModuleBase::IsCompatibleWithBindGroupLayout(size_t group, const BindGroupLayoutBase* layout) {
|
bool ShaderModuleBase::IsCompatibleWithBindGroupLayout(size_t group, const BindGroupLayoutBase* layout) {
|
||||||
const auto& layoutInfo = layout->GetBindingInfo();
|
const auto& layoutInfo = layout->GetBindingInfo();
|
||||||
for (size_t i = 0; i < kMaxBindingsPerGroup; ++i) {
|
for (size_t i = 0; i < kMaxBindingsPerGroup; ++i) {
|
||||||
const auto& moduleInfo = bindingInfo[group][i];
|
const auto& moduleInfo = mBindingInfo[group][i];
|
||||||
|
|
||||||
if (!moduleInfo.used) {
|
if (!moduleInfo.used) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -199,7 +199,7 @@ namespace backend {
|
||||||
if (moduleInfo.type != layoutInfo.types[i]) {
|
if (moduleInfo.type != layoutInfo.types[i]) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ((layoutInfo.visibilities[i] & StageBit(executionModel)) == 0) {
|
if ((layoutInfo.visibilities[i] & StageBit(mExecutionModel)) == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -211,20 +211,20 @@ namespace backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint32_t> ShaderModuleBuilder::AcquireSpirv() {
|
std::vector<uint32_t> ShaderModuleBuilder::AcquireSpirv() {
|
||||||
return std::move(spirv);
|
return std::move(mSpirv);
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderModuleBase* ShaderModuleBuilder::GetResultImpl() {
|
ShaderModuleBase* ShaderModuleBuilder::GetResultImpl() {
|
||||||
if (spirv.size() == 0) {
|
if (mSpirv.size() == 0) {
|
||||||
HandleError("Shader module needs to have the source set");
|
HandleError("Shader module needs to have the source set");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return device->CreateShaderModule(this);
|
return mDevice->CreateShaderModule(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShaderModuleBuilder::SetSource(uint32_t codeSize, const uint32_t* code) {
|
void ShaderModuleBuilder::SetSource(uint32_t codeSize, const uint32_t* code) {
|
||||||
spirv.assign(code, code + codeSize);
|
mSpirv.assign(code, code + codeSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,11 +67,11 @@ namespace backend {
|
||||||
private:
|
private:
|
||||||
bool IsCompatibleWithBindGroupLayout(size_t group, const BindGroupLayoutBase* layout);
|
bool IsCompatibleWithBindGroupLayout(size_t group, const BindGroupLayoutBase* layout);
|
||||||
|
|
||||||
DeviceBase* device;
|
DeviceBase* mDevice;
|
||||||
PushConstantInfo pushConstants = {};
|
PushConstantInfo mPushConstants = {};
|
||||||
ModuleBindingInfo bindingInfo;
|
ModuleBindingInfo mBindingInfo;
|
||||||
std::bitset<kMaxVertexAttributes> usedVertexAttributes;
|
std::bitset<kMaxVertexAttributes> mUsedVertexAttributes;
|
||||||
nxt::ShaderStage executionModel;
|
nxt::ShaderStage mExecutionModel;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ShaderModuleBuilder : public Builder<ShaderModuleBase> {
|
class ShaderModuleBuilder : public Builder<ShaderModuleBase> {
|
||||||
|
@ -88,7 +88,7 @@ namespace backend {
|
||||||
|
|
||||||
ShaderModuleBase* GetResultImpl() override;
|
ShaderModuleBase* GetResultImpl() override;
|
||||||
|
|
||||||
std::vector<uint32_t> spirv;
|
std::vector<uint32_t> mSpirv;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace backend {
|
||||||
// SwapChain
|
// SwapChain
|
||||||
|
|
||||||
SwapChainBase::SwapChainBase(SwapChainBuilder* builder)
|
SwapChainBase::SwapChainBase(SwapChainBuilder* builder)
|
||||||
: device(builder->device), implementation(builder->implementation) {
|
: mDevice(builder->mDevice), mImplementation(builder->mImplementation) {
|
||||||
}
|
}
|
||||||
|
|
||||||
SwapChainBase::~SwapChainBase() {
|
SwapChainBase::~SwapChainBase() {
|
||||||
|
@ -31,58 +31,58 @@ namespace backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
DeviceBase* SwapChainBase::GetDevice() {
|
DeviceBase* SwapChainBase::GetDevice() {
|
||||||
return device;
|
return mDevice;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwapChainBase::Configure(nxt::TextureFormat format, nxt::TextureUsageBit allowedUsage, uint32_t width, uint32_t height) {
|
void SwapChainBase::Configure(nxt::TextureFormat format, nxt::TextureUsageBit allowedUsage, uint32_t width, uint32_t height) {
|
||||||
if (width == 0 || height == 0) {
|
if (width == 0 || height == 0) {
|
||||||
device->HandleError("Swap chain cannot be configured to zero size");
|
mDevice->HandleError("Swap chain cannot be configured to zero size");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
allowedUsage |= nxt::TextureUsageBit::Present;
|
allowedUsage |= nxt::TextureUsageBit::Present;
|
||||||
|
|
||||||
this->format = format;
|
mFormat = format;
|
||||||
this->allowedUsage = allowedUsage;
|
mAllowedUsage = allowedUsage;
|
||||||
this->width = width;
|
mWidth = width;
|
||||||
this->height = height;
|
mHeight = height;
|
||||||
implementation.Configure(implementation.userData,
|
mImplementation.Configure(mImplementation.userData,
|
||||||
static_cast<nxtTextureFormat>(format), static_cast<nxtTextureUsageBit>(allowedUsage), width, height);
|
static_cast<nxtTextureFormat>(format), static_cast<nxtTextureUsageBit>(allowedUsage), width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureBase* SwapChainBase::GetNextTexture() {
|
TextureBase* SwapChainBase::GetNextTexture() {
|
||||||
if (width == 0) {
|
if (mWidth == 0) {
|
||||||
// If width is 0, it implies swap chain has never been configured
|
// If width is 0, it implies swap chain has never been configured
|
||||||
device->HandleError("Swap chain needs to be configured before GetNextTexture");
|
mDevice->HandleError("Swap chain needs to be configured before GetNextTexture");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* builder = device->CreateTextureBuilder();
|
auto* builder = mDevice->CreateTextureBuilder();
|
||||||
builder->SetDimension(nxt::TextureDimension::e2D);
|
builder->SetDimension(nxt::TextureDimension::e2D);
|
||||||
builder->SetExtent(width, height, 1);
|
builder->SetExtent(mWidth, mHeight, 1);
|
||||||
builder->SetFormat(format);
|
builder->SetFormat(mFormat);
|
||||||
builder->SetMipLevels(1);
|
builder->SetMipLevels(1);
|
||||||
builder->SetAllowedUsage(allowedUsage);
|
builder->SetAllowedUsage(mAllowedUsage);
|
||||||
|
|
||||||
auto* texture = GetNextTextureImpl(builder);
|
auto* texture = GetNextTextureImpl(builder);
|
||||||
lastNextTexture = texture;
|
mLastNextTexture = texture;
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwapChainBase::Present(TextureBase* texture) {
|
void SwapChainBase::Present(TextureBase* texture) {
|
||||||
if (texture != lastNextTexture) {
|
if (texture != mLastNextTexture) {
|
||||||
device->HandleError("Tried to present something other than the last NextTexture");
|
mDevice->HandleError("Tried to present something other than the last NextTexture");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (texture->GetUsage() != nxt::TextureUsageBit::Present) {
|
if (texture->GetUsage() != nxt::TextureUsageBit::Present) {
|
||||||
device->HandleError("Texture has not been transitioned to the Present usage");
|
mDevice->HandleError("Texture has not been transitioned to the Present usage");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
implementation.Present(implementation.userData);
|
mImplementation.Present(mImplementation.userData);
|
||||||
}
|
}
|
||||||
|
|
||||||
const nxtSwapChainImplementation& SwapChainBase::GetImplementation() {
|
const nxtSwapChainImplementation& SwapChainBase::GetImplementation() {
|
||||||
return implementation;
|
return mImplementation;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SwapChain Builder
|
// SwapChain Builder
|
||||||
|
@ -92,11 +92,11 @@ namespace backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
SwapChainBase* SwapChainBuilder::GetResultImpl() {
|
SwapChainBase* SwapChainBuilder::GetResultImpl() {
|
||||||
if (!implementation.Init) {
|
if (!mImplementation.Init) {
|
||||||
HandleError("Implementation not set");
|
HandleError("Implementation not set");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return device->CreateSwapChain(this);
|
return mDevice->CreateSwapChain(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwapChainBuilder::SetImplementation(uint64_t implementation) {
|
void SwapChainBuilder::SetImplementation(uint64_t implementation) {
|
||||||
|
@ -113,6 +113,6 @@ namespace backend {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->implementation = impl;
|
mImplementation = impl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,13 +41,13 @@ namespace backend {
|
||||||
virtual TextureBase* GetNextTextureImpl(TextureBuilder* builder) = 0;
|
virtual TextureBase* GetNextTextureImpl(TextureBuilder* builder) = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DeviceBase* device = nullptr;
|
DeviceBase* mDevice = nullptr;
|
||||||
nxtSwapChainImplementation implementation = {};
|
nxtSwapChainImplementation mImplementation = {};
|
||||||
nxt::TextureFormat format = {};
|
nxt::TextureFormat mFormat = {};
|
||||||
nxt::TextureUsageBit allowedUsage;
|
nxt::TextureUsageBit mAllowedUsage;
|
||||||
uint32_t width = 0;
|
uint32_t mWidth = 0;
|
||||||
uint32_t height = 0;
|
uint32_t mHeight = 0;
|
||||||
TextureBase* lastNextTexture = nullptr;
|
TextureBase* mLastNextTexture = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SwapChainBuilder : public Builder<SwapChainBase> {
|
class SwapChainBuilder : public Builder<SwapChainBase> {
|
||||||
|
@ -61,7 +61,7 @@ namespace backend {
|
||||||
private:
|
private:
|
||||||
friend class SwapChainBase;
|
friend class SwapChainBase;
|
||||||
|
|
||||||
nxtSwapChainImplementation implementation = {};
|
nxtSwapChainImplementation mImplementation = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,50 +75,50 @@ namespace backend {
|
||||||
// TextureBase
|
// TextureBase
|
||||||
|
|
||||||
TextureBase::TextureBase(TextureBuilder* builder)
|
TextureBase::TextureBase(TextureBuilder* builder)
|
||||||
: device(builder->device), dimension(builder->dimension), format(builder->format), width(builder->width),
|
: mDevice(builder->mDevice), mDimension(builder->mDimension), mFormat(builder->mFormat), mWidth(builder->mWidth),
|
||||||
height(builder->height), depth(builder->depth), numMipLevels(builder->numMipLevels),
|
mHeight(builder->mHeight), mDepth(builder->mDepth), mNumMipLevels(builder->mNumMipLevels),
|
||||||
allowedUsage(builder->allowedUsage), currentUsage(builder->currentUsage) {
|
mAllowedUsage(builder->mAllowedUsage), mCurrentUsage(builder->mCurrentUsage) {
|
||||||
}
|
}
|
||||||
|
|
||||||
DeviceBase* TextureBase::GetDevice() {
|
DeviceBase* TextureBase::GetDevice() {
|
||||||
return device;
|
return mDevice;
|
||||||
}
|
}
|
||||||
|
|
||||||
nxt::TextureDimension TextureBase::GetDimension() const {
|
nxt::TextureDimension TextureBase::GetDimension() const {
|
||||||
return dimension;
|
return mDimension;
|
||||||
}
|
}
|
||||||
nxt::TextureFormat TextureBase::GetFormat() const {
|
nxt::TextureFormat TextureBase::GetFormat() const {
|
||||||
return format;
|
return mFormat;
|
||||||
}
|
}
|
||||||
uint32_t TextureBase::GetWidth() const {
|
uint32_t TextureBase::GetWidth() const {
|
||||||
return width;
|
return mWidth;
|
||||||
}
|
}
|
||||||
uint32_t TextureBase::GetHeight() const {
|
uint32_t TextureBase::GetHeight() const {
|
||||||
return height;
|
return mHeight;
|
||||||
}
|
}
|
||||||
uint32_t TextureBase::GetDepth() const {
|
uint32_t TextureBase::GetDepth() const {
|
||||||
return depth;
|
return mDepth;
|
||||||
}
|
}
|
||||||
uint32_t TextureBase::GetNumMipLevels() const {
|
uint32_t TextureBase::GetNumMipLevels() const {
|
||||||
return numMipLevels;
|
return mNumMipLevels;
|
||||||
}
|
}
|
||||||
nxt::TextureUsageBit TextureBase::GetAllowedUsage() const {
|
nxt::TextureUsageBit TextureBase::GetAllowedUsage() const {
|
||||||
return allowedUsage;
|
return mAllowedUsage;
|
||||||
}
|
}
|
||||||
nxt::TextureUsageBit TextureBase::GetUsage() const {
|
nxt::TextureUsageBit TextureBase::GetUsage() const {
|
||||||
return currentUsage;
|
return mCurrentUsage;
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureViewBuilder* TextureBase::CreateTextureViewBuilder() {
|
TextureViewBuilder* TextureBase::CreateTextureViewBuilder() {
|
||||||
return new TextureViewBuilder(device, this);
|
return new TextureViewBuilder(mDevice, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TextureBase::IsFrozen() const {
|
bool TextureBase::IsFrozen() const {
|
||||||
return frozen;
|
return mIsFrozen;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TextureBase::HasFrozenUsage(nxt::TextureUsageBit usage) const {
|
bool TextureBase::HasFrozenUsage(nxt::TextureUsageBit usage) const {
|
||||||
return frozen && (usage & allowedUsage);
|
return mIsFrozen && (usage & mAllowedUsage);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TextureBase::IsUsagePossible(nxt::TextureUsageBit allowedUsage, nxt::TextureUsageBit usage) {
|
bool TextureBase::IsUsagePossible(nxt::TextureUsageBit allowedUsage, nxt::TextureUsageBit usage) {
|
||||||
|
@ -128,38 +128,38 @@ namespace backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TextureBase::IsTransitionPossible(nxt::TextureUsageBit usage) const {
|
bool TextureBase::IsTransitionPossible(nxt::TextureUsageBit usage) const {
|
||||||
if (frozen) {
|
if (mIsFrozen) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (currentUsage == nxt::TextureUsageBit::Present) {
|
if (mCurrentUsage == nxt::TextureUsageBit::Present) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return IsUsagePossible(allowedUsage, usage);
|
return IsUsagePossible(mAllowedUsage, usage);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureBase::UpdateUsageInternal(nxt::TextureUsageBit usage) {
|
void TextureBase::UpdateUsageInternal(nxt::TextureUsageBit usage) {
|
||||||
ASSERT(IsTransitionPossible(usage));
|
ASSERT(IsTransitionPossible(usage));
|
||||||
currentUsage = usage;
|
mCurrentUsage = usage;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureBase::TransitionUsage(nxt::TextureUsageBit usage) {
|
void TextureBase::TransitionUsage(nxt::TextureUsageBit usage) {
|
||||||
if (!IsTransitionPossible(usage)) {
|
if (!IsTransitionPossible(usage)) {
|
||||||
device->HandleError("Texture frozen or usage not allowed");
|
mDevice->HandleError("Texture frozen or usage not allowed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
TransitionUsageImpl(currentUsage, usage);
|
TransitionUsageImpl(mCurrentUsage, usage);
|
||||||
UpdateUsageInternal(usage);
|
UpdateUsageInternal(usage);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureBase::FreezeUsage(nxt::TextureUsageBit usage) {
|
void TextureBase::FreezeUsage(nxt::TextureUsageBit usage) {
|
||||||
if (!IsTransitionPossible(usage)) {
|
if (!IsTransitionPossible(usage)) {
|
||||||
device->HandleError("Texture frozen or usage not allowed");
|
mDevice->HandleError("Texture frozen or usage not allowed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
allowedUsage = usage;
|
mAllowedUsage = usage;
|
||||||
TransitionUsageImpl(currentUsage, usage);
|
TransitionUsageImpl(mCurrentUsage, usage);
|
||||||
UpdateUsageInternal(usage);
|
UpdateUsageInternal(usage);
|
||||||
frozen = true;
|
mIsFrozen = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TextureBuilder
|
// TextureBuilder
|
||||||
|
@ -180,33 +180,33 @@ namespace backend {
|
||||||
TextureBase* TextureBuilder::GetResultImpl() {
|
TextureBase* TextureBuilder::GetResultImpl() {
|
||||||
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 ((mPropertiesSet & allProperties) != allProperties) {
|
||||||
HandleError("Texture missing properties");
|
HandleError("Texture missing properties");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!TextureBase::IsUsagePossible(allowedUsage, currentUsage)) {
|
if (!TextureBase::IsUsagePossible(mAllowedUsage, mCurrentUsage)) {
|
||||||
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
|
||||||
|
|
||||||
return device->CreateTexture(this);
|
return mDevice->CreateTexture(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureBuilder::SetDimension(nxt::TextureDimension dimension) {
|
void TextureBuilder::SetDimension(nxt::TextureDimension dimension) {
|
||||||
if ((propertiesSet & TEXTURE_PROPERTY_DIMENSION) != 0) {
|
if ((mPropertiesSet & TEXTURE_PROPERTY_DIMENSION) != 0) {
|
||||||
HandleError("Texture dimension property set multiple times");
|
HandleError("Texture dimension property set multiple times");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
propertiesSet |= TEXTURE_PROPERTY_DIMENSION;
|
mPropertiesSet |= TEXTURE_PROPERTY_DIMENSION;
|
||||||
this->dimension = dimension;
|
mDimension = dimension;
|
||||||
}
|
}
|
||||||
|
|
||||||
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 ((mPropertiesSet & TEXTURE_PROPERTY_EXTENT) != 0) {
|
||||||
HandleError("Texture extent property set multiple times");
|
HandleError("Texture extent property set multiple times");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -216,70 +216,70 @@ namespace backend {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
propertiesSet |= TEXTURE_PROPERTY_EXTENT;
|
mPropertiesSet |= TEXTURE_PROPERTY_EXTENT;
|
||||||
this->width = width;
|
mWidth = width;
|
||||||
this->height = height;
|
mHeight = height;
|
||||||
this->depth = depth;
|
mDepth = depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureBuilder::SetFormat(nxt::TextureFormat format) {
|
void TextureBuilder::SetFormat(nxt::TextureFormat format) {
|
||||||
if ((propertiesSet & TEXTURE_PROPERTY_FORMAT) != 0) {
|
if ((mPropertiesSet & TEXTURE_PROPERTY_FORMAT) != 0) {
|
||||||
HandleError("Texture format property set multiple times");
|
HandleError("Texture format property set multiple times");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
propertiesSet |= TEXTURE_PROPERTY_FORMAT;
|
mPropertiesSet |= TEXTURE_PROPERTY_FORMAT;
|
||||||
this->format = format;
|
mFormat = format;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureBuilder::SetMipLevels(uint32_t numMipLevels) {
|
void TextureBuilder::SetMipLevels(uint32_t numMipLevels) {
|
||||||
if ((propertiesSet & TEXTURE_PROPERTY_MIP_LEVELS) != 0) {
|
if ((mPropertiesSet & TEXTURE_PROPERTY_MIP_LEVELS) != 0) {
|
||||||
HandleError("Texture mip levels property set multiple times");
|
HandleError("Texture mip levels property set multiple times");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
propertiesSet |= TEXTURE_PROPERTY_MIP_LEVELS;
|
mPropertiesSet |= TEXTURE_PROPERTY_MIP_LEVELS;
|
||||||
this->numMipLevels = numMipLevels;
|
mNumMipLevels = numMipLevels;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureBuilder::SetAllowedUsage(nxt::TextureUsageBit usage) {
|
void TextureBuilder::SetAllowedUsage(nxt::TextureUsageBit usage) {
|
||||||
if ((propertiesSet & TEXTURE_PROPERTY_ALLOWED_USAGE) != 0) {
|
if ((mPropertiesSet & TEXTURE_PROPERTY_ALLOWED_USAGE) != 0) {
|
||||||
HandleError("Texture allowed usage property set multiple times");
|
HandleError("Texture allowed usage property set multiple times");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
propertiesSet |= TEXTURE_PROPERTY_ALLOWED_USAGE;
|
mPropertiesSet |= TEXTURE_PROPERTY_ALLOWED_USAGE;
|
||||||
this->allowedUsage = usage;
|
mAllowedUsage = usage;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureBuilder::SetInitialUsage(nxt::TextureUsageBit usage) {
|
void TextureBuilder::SetInitialUsage(nxt::TextureUsageBit usage) {
|
||||||
if ((propertiesSet & TEXTURE_PROPERTY_INITIAL_USAGE) != 0) {
|
if ((mPropertiesSet & TEXTURE_PROPERTY_INITIAL_USAGE) != 0) {
|
||||||
HandleError("Texture initial usage property set multiple times");
|
HandleError("Texture initial usage property set multiple times");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
propertiesSet |= TEXTURE_PROPERTY_INITIAL_USAGE;
|
mPropertiesSet |= TEXTURE_PROPERTY_INITIAL_USAGE;
|
||||||
this->currentUsage = usage;
|
mCurrentUsage = usage;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TextureViewBase
|
// TextureViewBase
|
||||||
|
|
||||||
TextureViewBase::TextureViewBase(TextureViewBuilder* builder)
|
TextureViewBase::TextureViewBase(TextureViewBuilder* builder)
|
||||||
: texture(builder->texture) {
|
: mTexture(builder->mTexture) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureBase* TextureViewBase::GetTexture() {
|
TextureBase* TextureViewBase::GetTexture() {
|
||||||
return texture.Get();
|
return mTexture.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TextureViewBuilder
|
// TextureViewBuilder
|
||||||
|
|
||||||
TextureViewBuilder::TextureViewBuilder(DeviceBase* device, TextureBase* texture)
|
TextureViewBuilder::TextureViewBuilder(DeviceBase* device, TextureBase* texture)
|
||||||
: Builder(device), texture(texture) {
|
: Builder(device), mTexture(texture) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureViewBase* TextureViewBuilder::GetResultImpl() {
|
TextureViewBase* TextureViewBuilder::GetResultImpl() {
|
||||||
return device->CreateTextureView(this);
|
return mDevice->CreateTextureView(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,15 +56,15 @@ namespace backend {
|
||||||
virtual void TransitionUsageImpl(nxt::TextureUsageBit currentUsage, nxt::TextureUsageBit targetUsage) = 0;
|
virtual void TransitionUsageImpl(nxt::TextureUsageBit currentUsage, nxt::TextureUsageBit targetUsage) = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DeviceBase* device;
|
DeviceBase* mDevice;
|
||||||
|
|
||||||
nxt::TextureDimension dimension;
|
nxt::TextureDimension mDimension;
|
||||||
nxt::TextureFormat format;
|
nxt::TextureFormat mFormat;
|
||||||
uint32_t width, height, depth;
|
uint32_t mWidth, mHeight, mDepth;
|
||||||
uint32_t numMipLevels;
|
uint32_t mNumMipLevels;
|
||||||
nxt::TextureUsageBit allowedUsage = nxt::TextureUsageBit::None;
|
nxt::TextureUsageBit mAllowedUsage = nxt::TextureUsageBit::None;
|
||||||
nxt::TextureUsageBit currentUsage = nxt::TextureUsageBit::None;
|
nxt::TextureUsageBit mCurrentUsage = nxt::TextureUsageBit::None;
|
||||||
bool frozen = false;
|
bool mIsFrozen = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TextureBuilder : public Builder<TextureBase> {
|
class TextureBuilder : public Builder<TextureBase> {
|
||||||
|
@ -84,14 +84,14 @@ namespace backend {
|
||||||
|
|
||||||
TextureBase* GetResultImpl() override;
|
TextureBase* GetResultImpl() override;
|
||||||
|
|
||||||
int propertiesSet = 0;
|
int mPropertiesSet = 0;
|
||||||
|
|
||||||
nxt::TextureDimension dimension;
|
nxt::TextureDimension mDimension;
|
||||||
uint32_t width, height, depth;
|
uint32_t mWidth, mHeight, mDepth;
|
||||||
nxt::TextureFormat format;
|
nxt::TextureFormat mFormat;
|
||||||
uint32_t numMipLevels;
|
uint32_t mNumMipLevels;
|
||||||
nxt::TextureUsageBit allowedUsage = nxt::TextureUsageBit::None;
|
nxt::TextureUsageBit mAllowedUsage = nxt::TextureUsageBit::None;
|
||||||
nxt::TextureUsageBit currentUsage = nxt::TextureUsageBit::None;
|
nxt::TextureUsageBit mCurrentUsage = nxt::TextureUsageBit::None;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TextureViewBase : public RefCounted {
|
class TextureViewBase : public RefCounted {
|
||||||
|
@ -101,7 +101,7 @@ namespace backend {
|
||||||
TextureBase* GetTexture();
|
TextureBase* GetTexture();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ref<TextureBase> texture;
|
Ref<TextureBase> mTexture;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TextureViewBuilder : public Builder<TextureViewBase> {
|
class TextureViewBuilder : public Builder<TextureViewBase> {
|
||||||
|
@ -113,7 +113,7 @@ namespace backend {
|
||||||
|
|
||||||
TextureViewBase* GetResultImpl() override;
|
TextureViewBase* GetResultImpl() override;
|
||||||
|
|
||||||
Ref<TextureBase> texture;
|
Ref<TextureBase> mTexture;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue