Use a descriptor for BindGroupLayout (#211)

* Use a descriptor for BindGroupLayout
* Fix MatchesLambda
* Add WireTests.StructureOfStructureArrayArgument
* Add BindGroupValidationTests.BindGroupLayoutCache
This commit is contained in:
Kai Ninomiya
2018-07-10 12:23:50 -07:00
committed by GitHub
parent 7883e7e59c
commit 234becf175
32 changed files with 259 additions and 163 deletions

View File

@@ -15,6 +15,7 @@
#include "backend/BindGroupLayout.h"
#include "backend/Device.h"
#include "backend/ValidationUtils_autogen.h"
#include "common/BitSetIterator.h"
#include "common/HashUtils.h"
@@ -22,6 +23,24 @@
namespace backend {
MaybeError ValidateBindGroupLayoutDescriptor(DeviceBase*,
const nxt::BindGroupLayoutDescriptor* descriptor) {
NXT_TRY_ASSERT(descriptor->nextInChain == nullptr, "nextInChain must be nullptr");
std::bitset<kMaxBindingsPerGroup> bindingsSet;
for (uint32_t i = 0; i < descriptor->numBindings; ++i) {
auto& binding = descriptor->bindings[i];
NXT_TRY_ASSERT(binding.binding <= kMaxBindingsPerGroup,
"some binding index exceeds the maximum value");
NXT_TRY(ValidateShaderStageBit(binding.visibility));
NXT_TRY(ValidateBindingType(binding.type));
NXT_TRY_ASSERT(!bindingsSet[i], "some binding index was specified more than once");
bindingsSet.set(binding.binding);
}
return {};
}
namespace {
size_t HashBindingInfo(const BindGroupLayoutBase::LayoutBindingInfo& info) {
size_t hash = Hash(info.mask);
@@ -52,8 +71,20 @@ namespace backend {
// BindGroupLayoutBase
BindGroupLayoutBase::BindGroupLayoutBase(BindGroupLayoutBuilder* builder, bool blueprint)
: mDevice(builder->mDevice), mBindingInfo(builder->mBindingInfo), mIsBlueprint(blueprint) {
BindGroupLayoutBase::BindGroupLayoutBase(DeviceBase* device,
const nxt::BindGroupLayoutDescriptor* descriptor,
bool blueprint)
: mDevice(device), mIsBlueprint(blueprint) {
for (uint32_t i = 0; i < descriptor->numBindings; ++i) {
auto& binding = descriptor->bindings[i];
uint32_t index = binding.binding;
mBindingInfo.visibilities[index] = binding.visibility;
mBindingInfo.types[index] = binding.type;
ASSERT(!mBindingInfo.mask[index]);
mBindingInfo.mask.set(index);
}
}
BindGroupLayoutBase::~BindGroupLayoutBase() {
@@ -71,44 +102,6 @@ namespace backend {
return mDevice;
}
// BindGroupLayoutBuilder
BindGroupLayoutBuilder::BindGroupLayoutBuilder(DeviceBase* device) : Builder(device) {
}
const BindGroupLayoutBase::LayoutBindingInfo& BindGroupLayoutBuilder::GetBindingInfo() const {
return mBindingInfo;
}
BindGroupLayoutBase* BindGroupLayoutBuilder::GetResultImpl() {
BindGroupLayoutBase blueprint(this, true);
auto* result = mDevice->GetOrCreateBindGroupLayout(&blueprint, this);
return result;
}
void BindGroupLayoutBuilder::SetBindingsType(nxt::ShaderStageBit visibility,
nxt::BindingType bindingType,
uint32_t start,
uint32_t count) {
if (start + count > kMaxBindingsPerGroup) {
HandleError("Setting bindings type over maximum number of bindings");
return;
}
for (size_t i = start; i < start + count; i++) {
if (mBindingInfo.mask[i]) {
HandleError("Setting already set binding type");
return;
}
}
for (size_t i = start; i < start + count; i++) {
mBindingInfo.mask.set(i);
mBindingInfo.visibilities[i] = visibility;
mBindingInfo.types[i] = bindingType;
}
}
// BindGroupLayoutCacheFuncs
size_t BindGroupLayoutCacheFuncs::operator()(const BindGroupLayoutBase* bgl) const {

View File

@@ -15,7 +15,7 @@
#ifndef BACKEND_BINDGROUPLAYOUT_H_
#define BACKEND_BINDGROUPLAYOUT_H_
#include "backend/Builder.h"
#include "backend/Error.h"
#include "backend/Forward.h"
#include "backend/RefCounted.h"
#include "common/Constants.h"
@@ -27,9 +27,14 @@
namespace backend {
MaybeError ValidateBindGroupLayoutDescriptor(DeviceBase*,
const nxt::BindGroupLayoutDescriptor* descriptor);
class BindGroupLayoutBase : public RefCounted {
public:
BindGroupLayoutBase(BindGroupLayoutBuilder* builder, bool blueprint = false);
BindGroupLayoutBase(DeviceBase* device,
const nxt::BindGroupLayoutDescriptor* descriptor,
bool blueprint = false);
~BindGroupLayoutBase() override;
struct LayoutBindingInfo {
@@ -47,26 +52,6 @@ namespace backend {
bool mIsBlueprint = false;
};
class BindGroupLayoutBuilder : public Builder<BindGroupLayoutBase> {
public:
BindGroupLayoutBuilder(DeviceBase* device);
const BindGroupLayoutBase::LayoutBindingInfo& GetBindingInfo() const;
// NXT API
void SetBindingsType(nxt::ShaderStageBit visibility,
nxt::BindingType bindingType,
uint32_t start,
uint32_t count);
private:
friend class BindGroupLayoutBase;
BindGroupLayoutBase* GetResultImpl() override;
BindGroupLayoutBase::LayoutBindingInfo mBindingInfo;
};
// Implements the functors necessary for the unordered_set<BGL*>-based cache.
struct BindGroupLayoutCacheFuncs {
// The hash function

View File

@@ -73,20 +73,18 @@ namespace backend {
return this;
}
BindGroupLayoutBase* DeviceBase::GetOrCreateBindGroupLayout(
const BindGroupLayoutBase* blueprint,
BindGroupLayoutBuilder* builder) {
// The blueprint is only used to search in the cache and is not modified. However cached
// objects can be modified, and unordered_set cannot search for a const pointer in a non
// const pointer set. That's why we do a const_cast here, but the blueprint won't be
// modified.
auto iter = mCaches->bindGroupLayouts.find(const_cast<BindGroupLayoutBase*>(blueprint));
ResultOrError<BindGroupLayoutBase*> DeviceBase::GetOrCreateBindGroupLayout(
const nxt::BindGroupLayoutDescriptor* descriptor) {
BindGroupLayoutBase blueprint(this, descriptor, true);
auto iter = mCaches->bindGroupLayouts.find(&blueprint);
if (iter != mCaches->bindGroupLayouts.end()) {
(*iter)->Reference();
return *iter;
}
BindGroupLayoutBase* backendObj = CreateBindGroupLayout(builder);
BindGroupLayoutBase* backendObj;
NXT_TRY_ASSIGN(backendObj, CreateBindGroupLayoutImpl(descriptor));
mCaches->bindGroupLayouts.insert(backendObj);
return backendObj;
}
@@ -98,8 +96,22 @@ namespace backend {
BindGroupBuilder* DeviceBase::CreateBindGroupBuilder() {
return new BindGroupBuilder(this);
}
BindGroupLayoutBuilder* DeviceBase::CreateBindGroupLayoutBuilder() {
return new BindGroupLayoutBuilder(this);
BindGroupLayoutBase* DeviceBase::CreateBindGroupLayout(
const nxt::BindGroupLayoutDescriptor* descriptor) {
MaybeError validation = ValidateBindGroupLayoutDescriptor(this, descriptor);
if (validation.IsError()) {
// TODO(cwallez@chromium.org): Implement the WebGPU error handling mechanism.
delete validation.AcquireError();
return nullptr;
}
auto maybeBindGroupLayout = GetOrCreateBindGroupLayout(descriptor);
if (maybeBindGroupLayout.IsError()) {
// TODO(cwallez@chromium.org): Implement the WebGPU error handling mechanism.
delete maybeBindGroupLayout.AcquireError();
return nullptr;
}
return maybeBindGroupLayout.AcquireSuccess();
}
BlendStateBuilder* DeviceBase::CreateBlendStateBuilder() {
return new BlendStateBuilder(this);

View File

@@ -36,7 +36,6 @@ namespace backend {
DeviceBase* GetDevice();
virtual BindGroupBase* CreateBindGroup(BindGroupBuilder* builder) = 0;
virtual BindGroupLayoutBase* CreateBindGroupLayout(BindGroupLayoutBuilder* builder) = 0;
virtual BlendStateBase* CreateBlendState(BlendStateBuilder* builder) = 0;
virtual BufferBase* CreateBuffer(BufferBuilder* builder) = 0;
virtual BufferViewBase* CreateBufferView(BufferViewBuilder* builder) = 0;
@@ -69,13 +68,14 @@ namespace backend {
// the built object will be, the "blueprint". The blueprint is just a FooBase object
// instead of a backend Foo object. If the blueprint doesn't match an object in the
// cache, then the builder is used to make a new object.
BindGroupLayoutBase* GetOrCreateBindGroupLayout(const BindGroupLayoutBase* blueprint,
BindGroupLayoutBuilder* builder);
ResultOrError<BindGroupLayoutBase*> GetOrCreateBindGroupLayout(
const nxt::BindGroupLayoutDescriptor* descriptor);
void UncacheBindGroupLayout(BindGroupLayoutBase* obj);
// NXT API
BindGroupBuilder* CreateBindGroupBuilder();
BindGroupLayoutBuilder* CreateBindGroupLayoutBuilder();
BindGroupLayoutBase* CreateBindGroupLayout(
const nxt::BindGroupLayoutDescriptor* descriptor);
BlendStateBuilder* CreateBlendStateBuilder();
BufferBuilder* CreateBufferBuilder();
CommandBufferBuilder* CreateCommandBufferBuilder();
@@ -97,6 +97,8 @@ namespace backend {
void Release();
private:
virtual ResultOrError<BindGroupLayoutBase*> CreateBindGroupLayoutImpl(
const nxt::BindGroupLayoutDescriptor* descriptor) = 0;
virtual ResultOrError<PipelineLayoutBase*> CreatePipelineLayoutImpl(
const nxt::PipelineLayoutDescriptor* descriptor) = 0;
virtual ResultOrError<QueueBase*> CreateQueueImpl() = 0;

View File

@@ -19,8 +19,9 @@
namespace backend { namespace d3d12 {
BindGroupLayout::BindGroupLayout(Device* device, BindGroupLayoutBuilder* builder)
: BindGroupLayoutBase(builder), mDevice(device), mDescriptorCounts{} {
BindGroupLayout::BindGroupLayout(Device* device,
const nxt::BindGroupLayoutDescriptor* descriptor)
: BindGroupLayoutBase(device, descriptor), mDescriptorCounts{} {
const auto& groupInfo = GetBindingInfo();
for (uint32_t binding : IterateBitSet(groupInfo.mask)) {

View File

@@ -25,7 +25,7 @@ namespace backend { namespace d3d12 {
class BindGroupLayout : public BindGroupLayoutBase {
public:
BindGroupLayout(Device* device, BindGroupLayoutBuilder* builder);
BindGroupLayout(Device* device, const nxt::BindGroupLayoutDescriptor* descriptor);
enum DescriptorType {
CBV,
@@ -44,7 +44,6 @@ namespace backend { namespace d3d12 {
const D3D12_DESCRIPTOR_RANGE* GetSamplerDescriptorRanges() const;
private:
Device* mDevice;
std::array<uint32_t, kMaxBindingsPerGroup> mBindingOffsets;
std::array<uint32_t, DescriptorType::Count> mDescriptorCounts;
D3D12_DESCRIPTOR_RANGE mRanges[DescriptorType::Count];

View File

@@ -261,8 +261,9 @@ namespace backend { namespace d3d12 {
BindGroupBase* Device::CreateBindGroup(BindGroupBuilder* builder) {
return new BindGroup(this, builder);
}
BindGroupLayoutBase* Device::CreateBindGroupLayout(BindGroupLayoutBuilder* builder) {
return new BindGroupLayout(this, builder);
ResultOrError<BindGroupLayoutBase*> Device::CreateBindGroupLayoutImpl(
const nxt::BindGroupLayoutDescriptor* descriptor) {
return new BindGroupLayout(this, descriptor);
}
BlendStateBase* Device::CreateBlendState(BlendStateBuilder* builder) {
return new BlendState(builder);

View File

@@ -39,7 +39,6 @@ namespace backend { namespace d3d12 {
~Device();
BindGroupBase* CreateBindGroup(BindGroupBuilder* builder) override;
BindGroupLayoutBase* CreateBindGroupLayout(BindGroupLayoutBuilder* builder) override;
BlendStateBase* CreateBlendState(BlendStateBuilder* builder) override;
BufferBase* CreateBuffer(BufferBuilder* builder) override;
BufferViewBase* CreateBufferView(BufferViewBuilder* builder) override;
@@ -78,6 +77,8 @@ namespace backend { namespace d3d12 {
void ExecuteCommandLists(std::initializer_list<ID3D12CommandList*> commandLists);
private:
ResultOrError<BindGroupLayoutBase*> CreateBindGroupLayoutImpl(
const nxt::BindGroupLayoutDescriptor* descriptor) override;
ResultOrError<PipelineLayoutBase*> CreatePipelineLayoutImpl(
const nxt::PipelineLayoutDescriptor* descriptor) override;
ResultOrError<QueueBase*> CreateQueueImpl() override;

View File

@@ -36,7 +36,6 @@ namespace backend { namespace metal {
~Device();
BindGroupBase* CreateBindGroup(BindGroupBuilder* builder) override;
BindGroupLayoutBase* CreateBindGroupLayout(BindGroupLayoutBuilder* builder) override;
BlendStateBase* CreateBlendState(BlendStateBuilder* builder) override;
BufferBase* CreateBuffer(BufferBuilder* builder) override;
BufferViewBase* CreateBufferView(BufferViewBuilder* builder) override;
@@ -64,6 +63,8 @@ namespace backend { namespace metal {
ResourceUploader* GetResourceUploader() const;
private:
ResultOrError<BindGroupLayoutBase*> CreateBindGroupLayoutImpl(
const nxt::BindGroupLayoutDescriptor* descriptor) override;
ResultOrError<PipelineLayoutBase*> CreatePipelineLayoutImpl(
const nxt::PipelineLayoutDescriptor* descriptor) override;
ResultOrError<QueueBase*> CreateQueueImpl() override;

View File

@@ -85,8 +85,9 @@ namespace backend { namespace metal {
BindGroupBase* Device::CreateBindGroup(BindGroupBuilder* builder) {
return new BindGroup(builder);
}
BindGroupLayoutBase* Device::CreateBindGroupLayout(BindGroupLayoutBuilder* builder) {
return new BindGroupLayout(builder);
ResultOrError<BindGroupLayoutBase*> Device::CreateBindGroupLayoutImpl(
const nxt::BindGroupLayoutDescriptor* descriptor) {
return new BindGroupLayout(this, descriptor);
}
BlendStateBase* Device::CreateBlendState(BlendStateBuilder* builder) {
return new BlendState(builder);

View File

@@ -39,8 +39,9 @@ namespace backend { namespace null {
BindGroupBase* Device::CreateBindGroup(BindGroupBuilder* builder) {
return new BindGroup(builder);
}
BindGroupLayoutBase* Device::CreateBindGroupLayout(BindGroupLayoutBuilder* builder) {
return new BindGroupLayout(builder);
ResultOrError<BindGroupLayoutBase*> Device::CreateBindGroupLayoutImpl(
const nxt::BindGroupLayoutDescriptor* descriptor) {
return new BindGroupLayout(this, descriptor);
}
BlendStateBase* Device::CreateBlendState(BlendStateBuilder* builder) {
return new BlendState(builder);

View File

@@ -96,7 +96,6 @@ namespace backend { namespace null {
~Device();
BindGroupBase* CreateBindGroup(BindGroupBuilder* builder) override;
BindGroupLayoutBase* CreateBindGroupLayout(BindGroupLayoutBuilder* builder) override;
BlendStateBase* CreateBlendState(BlendStateBuilder* builder) override;
BufferBase* CreateBuffer(BufferBuilder* builder) override;
BufferViewBase* CreateBufferView(BufferViewBuilder* builder) override;
@@ -118,6 +117,8 @@ namespace backend { namespace null {
std::vector<std::unique_ptr<PendingOperation>> AcquirePendingOperations();
private:
ResultOrError<BindGroupLayoutBase*> CreateBindGroupLayoutImpl(
const nxt::BindGroupLayoutDescriptor* descriptor) override;
ResultOrError<PipelineLayoutBase*> CreatePipelineLayoutImpl(
const nxt::PipelineLayoutDescriptor* descriptor) override;
ResultOrError<QueueBase*> CreateQueueImpl() override;

View File

@@ -53,8 +53,9 @@ namespace backend { namespace opengl {
BindGroupBase* Device::CreateBindGroup(BindGroupBuilder* builder) {
return new BindGroup(builder);
}
BindGroupLayoutBase* Device::CreateBindGroupLayout(BindGroupLayoutBuilder* builder) {
return new BindGroupLayout(builder);
ResultOrError<BindGroupLayoutBase*> Device::CreateBindGroupLayoutImpl(
const nxt::BindGroupLayoutDescriptor* descriptor) {
return new BindGroupLayout(this, descriptor);
}
BlendStateBase* Device::CreateBlendState(BlendStateBuilder* builder) {
return new BlendState(builder);

View File

@@ -27,7 +27,6 @@ namespace backend { namespace opengl {
class Device : public DeviceBase {
public:
BindGroupBase* CreateBindGroup(BindGroupBuilder* builder) override;
BindGroupLayoutBase* CreateBindGroupLayout(BindGroupLayoutBuilder* builder) override;
BlendStateBase* CreateBlendState(BlendStateBuilder* builder) override;
BufferBase* CreateBuffer(BufferBuilder* builder) override;
BufferViewBase* CreateBufferView(BufferViewBuilder* builder) override;
@@ -46,6 +45,8 @@ namespace backend { namespace opengl {
void TickImpl() override;
private:
ResultOrError<BindGroupLayoutBase*> CreateBindGroupLayoutImpl(
const nxt::BindGroupLayoutDescriptor* descriptor) override;
ResultOrError<PipelineLayoutBase*> CreatePipelineLayoutImpl(
const nxt::PipelineLayoutDescriptor* descriptor) override;
ResultOrError<QueueBase*> CreateQueueImpl() override;

View File

@@ -54,8 +54,9 @@ namespace backend { namespace vulkan {
}
}
BindGroupLayout::BindGroupLayout(BindGroupLayoutBuilder* builder)
: BindGroupLayoutBase(builder) {
BindGroupLayout::BindGroupLayout(Device* device,
const nxt::BindGroupLayoutDescriptor* descriptor)
: BindGroupLayoutBase(device, descriptor) {
const auto& info = GetBindingInfo();
// Compute the bindings that will be chained in the DescriptorSetLayout create info. We add
@@ -81,7 +82,6 @@ namespace backend { namespace vulkan {
createInfo.bindingCount = numBindings;
createInfo.pBindings = bindings.data();
Device* device = ToBackend(GetDevice());
if (device->fn.CreateDescriptorSetLayout(device->GetVkDevice(), &createInfo, nullptr,
&mHandle) != VK_SUCCESS) {
ASSERT(false);

View File

@@ -27,7 +27,7 @@ namespace backend { namespace vulkan {
class BindGroupLayout : public BindGroupLayoutBase {
public:
BindGroupLayout(BindGroupLayoutBuilder* builder);
BindGroupLayout(Device* device, const nxt::BindGroupLayoutDescriptor* descriptor);
~BindGroupLayout();
VkDescriptorSetLayout GetHandle() const;

View File

@@ -217,8 +217,9 @@ namespace backend { namespace vulkan {
BindGroupBase* Device::CreateBindGroup(BindGroupBuilder* builder) {
return new BindGroup(builder);
}
BindGroupLayoutBase* Device::CreateBindGroupLayout(BindGroupLayoutBuilder* builder) {
return new BindGroupLayout(builder);
ResultOrError<BindGroupLayoutBase*> Device::CreateBindGroupLayoutImpl(
const nxt::BindGroupLayoutDescriptor* descriptor) {
return new BindGroupLayout(this, descriptor);
}
BlendStateBase* Device::CreateBlendState(BlendStateBuilder* builder) {
return new BlendState(builder);

View File

@@ -64,7 +64,6 @@ namespace backend { namespace vulkan {
// NXT API
BindGroupBase* CreateBindGroup(BindGroupBuilder* builder) override;
BindGroupLayoutBase* CreateBindGroupLayout(BindGroupLayoutBuilder* builder) override;
BlendStateBase* CreateBlendState(BlendStateBuilder* builder) override;
BufferBase* CreateBuffer(BufferBuilder* builder) override;
BufferViewBase* CreateBufferView(BufferViewBuilder* builder) override;
@@ -83,6 +82,8 @@ namespace backend { namespace vulkan {
void TickImpl() override;
private:
ResultOrError<BindGroupLayoutBase*> CreateBindGroupLayoutImpl(
const nxt::BindGroupLayoutDescriptor* descriptor) override;
ResultOrError<PipelineLayoutBase*> CreatePipelineLayoutImpl(
const nxt::PipelineLayoutDescriptor* descriptor) override;
ResultOrError<QueueBase*> CreateQueueImpl() override;