Use a descriptor for PipelineLayout (#206)

Adds support for structures inside descriptors.
This commit is contained in:
Kai Ninomiya 2018-06-27 16:21:39 -07:00 committed by GitHub
parent a2f9277dac
commit f53f98bf86
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
46 changed files with 192 additions and 158 deletions

View File

@ -228,9 +228,7 @@ void initSim() {
.SetBindingsType(nxt::ShaderStageBit::Compute, nxt::BindingType::StorageBuffer, 1, 2) .SetBindingsType(nxt::ShaderStageBit::Compute, nxt::BindingType::StorageBuffer, 1, 2)
.GetResult(); .GetResult();
nxt::PipelineLayout pl = device.CreatePipelineLayoutBuilder() nxt::PipelineLayout pl = utils::MakeBasicPipelineLayout(device, &bgl);
.SetBindGroupLayout(0, bgl)
.GetResult();
updatePipeline = device.CreateComputePipelineBuilder() updatePipeline = device.CreateComputePipelineBuilder()
.SetLayout(pl) .SetLayout(pl)

View File

@ -67,9 +67,7 @@ void init() {
.SetBindingsType(nxt::ShaderStageBit::Compute, nxt::BindingType::StorageBuffer, 0, 1) .SetBindingsType(nxt::ShaderStageBit::Compute, nxt::BindingType::StorageBuffer, 0, 1)
.GetResult(); .GetResult();
nxt::PipelineLayout pl = device.CreatePipelineLayoutBuilder() nxt::PipelineLayout pl = utils::MakeBasicPipelineLayout(device, &bgl);
.SetBindGroupLayout(0, bgl)
.GetResult();
computePipeline = device.CreateComputePipelineBuilder() computePipeline = device.CreateComputePipelineBuilder()
.SetLayout(pl) .SetLayout(pl)
@ -108,9 +106,7 @@ void init() {
.SetBindingsType(nxt::ShaderStageBit::Fragment, nxt::BindingType::UniformBuffer, 0, 1) .SetBindingsType(nxt::ShaderStageBit::Fragment, nxt::BindingType::UniformBuffer, 0, 1)
.GetResult(); .GetResult();
nxt::PipelineLayout pl = device.CreatePipelineLayoutBuilder() nxt::PipelineLayout pl = utils::MakeBasicPipelineLayout(device, &bgl);
.SetBindGroupLayout(0, bgl)
.GetResult();
depthStencilView = CreateDefaultDepthStencilView(device); depthStencilView = CreateDefaultDepthStencilView(device);

View File

@ -165,9 +165,7 @@ void init() {
.SetBindingsType(nxt::ShaderStageBit::Vertex, nxt::BindingType::UniformBuffer, 0, 2) .SetBindingsType(nxt::ShaderStageBit::Vertex, nxt::BindingType::UniformBuffer, 0, 2)
.GetResult(); .GetResult();
nxt::PipelineLayout pl = device.CreatePipelineLayoutBuilder() nxt::PipelineLayout pl = utils::MakeBasicPipelineLayout(device, &bgl);
.SetBindGroupLayout(0, bgl)
.GetResult();
cameraBuffer = device.CreateBufferBuilder() cameraBuffer = device.CreateBufferBuilder()
.SetAllowedUsage(nxt::BufferUsageBit::TransferDst | nxt::BufferUsageBit::Uniform) .SetAllowedUsage(nxt::BufferUsageBit::TransferDst | nxt::BufferUsageBit::Uniform)

View File

@ -115,9 +115,7 @@ void init() {
.SetBindingsType(nxt::ShaderStageBit::Fragment, nxt::BindingType::SampledTexture, 1, 1) .SetBindingsType(nxt::ShaderStageBit::Fragment, nxt::BindingType::SampledTexture, 1, 1)
.GetResult(); .GetResult();
nxt::PipelineLayout pl = device.CreatePipelineLayoutBuilder() nxt::PipelineLayout pl = utils::MakeBasicPipelineLayout(device, &bgl);
.SetBindGroupLayout(0, bgl)
.GetResult();
depthStencilView = CreateDefaultDepthStencilView(device); depthStencilView = CreateDefaultDepthStencilView(device);

View File

@ -58,9 +58,7 @@ void init() {
.SetBindingsType(nxt::ShaderStageBit::Fragment, nxt::BindingType::UniformBuffer, 0, 1) .SetBindingsType(nxt::ShaderStageBit::Fragment, nxt::BindingType::UniformBuffer, 0, 1)
.GetResult(); .GetResult();
nxt::PipelineLayout pl = device.CreatePipelineLayoutBuilder() nxt::PipelineLayout pl = utils::MakeBasicPipelineLayout(device, &bgl);
.SetBindGroupLayout(0, bgl)
.GetResult();
depthStencilView = CreateDefaultDepthStencilView(device); depthStencilView = CreateDefaultDepthStencilView(device);

View File

@ -127,9 +127,7 @@ void initPipelinePost() {
.SetBindingsType(nxt::ShaderStageBit::Fragment, nxt::BindingType::SampledTexture, 1, 1) .SetBindingsType(nxt::ShaderStageBit::Fragment, nxt::BindingType::SampledTexture, 1, 1)
.GetResult(); .GetResult();
nxt::PipelineLayout pl = device.CreatePipelineLayoutBuilder() nxt::PipelineLayout pl = utils::MakeBasicPipelineLayout(device, &bgl);
.SetBindGroupLayout(0, bgl)
.GetResult();
pipelinePost = device.CreateRenderPipelineBuilder() pipelinePost = device.CreateRenderPipelineBuilder()
.SetColorAttachmentFormat(0, nxt::TextureFormat::R8G8B8A8Unorm) .SetColorAttachmentFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)

View File

@ -286,9 +286,7 @@ namespace {
.SetDepthWriteEnabled(true) .SetDepthWriteEnabled(true)
.GetResult(); .GetResult();
auto pipelineLayout = device.CreatePipelineLayoutBuilder() auto pipelineLayout = utils::MakeBasicPipelineLayout(device, &bindGroupLayout);
.SetBindGroupLayout(0, bindGroupLayout)
.GetResult();
auto pipeline = device.CreateRenderPipelineBuilder() auto pipeline = device.CreateRenderPipelineBuilder()
.SetColorAttachmentFormat(0, GetPreferredSwapChainTextureFormat()) .SetColorAttachmentFormat(0, GetPreferredSwapChainTextureFormat())
.SetDepthStencilAttachmentFormat(nxt::TextureFormat::D32FloatS8Uint) .SetDepthStencilAttachmentFormat(nxt::TextureFormat::D32FloatS8Uint)

View File

@ -155,8 +155,18 @@ def link_structure(struct, types):
def make_member(m): def make_member(m):
return StructureMember(Name(m['name']), types[m['type']], m.get('annotation', 'value')) return StructureMember(Name(m['name']), types[m['type']], m.get('annotation', 'value'))
# TODO(cwallez@chromium.org): Handle pointer members and their length members = []
struct.members = [make_member(m) for m in struct.record['members']] members_by_name = {}
for m in struct.record['members']:
member = make_member(m)
members.append(member)
members_by_name[member.name.canonical_case()] = member
struct.members = members
for (member, m) in zip(members, struct.record['members']):
# TODO(kainino@chromium.org): More robust pointer/length handling?
if 'length' in m:
member.length = members_by_name[m['length']]
def parse_json(json): def parse_json(json):
category_to_parser = { category_to_parser = {

View File

@ -176,10 +176,10 @@
size_t memberLength = {{member_length(member, "record.")}}; size_t memberLength = {{member_length(member, "record.")}};
auto memberBuffer = reinterpret_cast<{{member_transfer_type(member)}}*>(buffer); auto memberBuffer = reinterpret_cast<{{member_transfer_type(member)}}*>(buffer);
buffer += memberLength * {{member_transfer_sizeof(member)}};
for (size_t i = 0; i < memberLength; ++i) { for (size_t i = 0; i < memberLength; ++i) {
{{serialize_member(member, "record." + memberName + "[i]", "memberBuffer[i]" )}} {{serialize_member(member, "record." + memberName + "[i]", "memberBuffer[i]" )}}
} }
buffer += memberLength * {{member_transfer_sizeof(member)}};
} }
{% endfor %} {% endfor %}
} }

View File

@ -608,8 +608,11 @@
"returns": "render pipeline builder" "returns": "render pipeline builder"
}, },
{ {
"name": "create pipeline layout builder", "name": "create pipeline layout",
"returns": "pipeline layout builder" "returns": "pipeline layout",
"args": [
{"name": "descriptor", "type": "pipeline layout descriptor", "annotation": "const*"}
]
}, },
{ {
"name": "create queue", "name": "create queue",
@ -770,20 +773,12 @@
"pipeline layout": { "pipeline layout": {
"category": "object" "category": "object"
}, },
"pipeline layout builder": { "pipeline layout descriptor": {
"category": "object", "category": "structure",
"methods": [ "extensible": true,
{ "members": [
"name": "get result", {"name": "num bind group layouts", "type": "uint32_t"},
"returns": "pipeline layout" {"name": "bind group layouts", "type": "bind group layout", "annotation": "const*", "length": "num bind group layouts"}
},
{
"name": "set bind group layout",
"args": [
{"name": "group index", "type": "uint32_t"},
{"name": "layout", "type": "bind group layout"}
]
}
] ]
}, },
"primitive topology": { "primitive topology": {

View File

@ -395,7 +395,8 @@ namespace backend {
for (size_t i = 0; i < mBindgroups.size(); ++i) { for (size_t i = 0; i < mBindgroups.size(); ++i) {
if (auto* bindgroup = mBindgroups[i]) { if (auto* bindgroup = mBindgroups[i]) {
// TODO(kainino@chromium.org): bind group compatibility // TODO(kainino@chromium.org): bind group compatibility
if (bindgroup->GetLayout() != mLastPipeline->GetLayout()->GetBindGroupLayout(i)) { auto* pipelineBGL = mLastPipeline->GetLayout()->GetBindGroupLayout(i);
if (pipelineBGL && bindgroup->GetLayout() != pipelineBGL) {
return false; return false;
} }
} }

View File

@ -119,8 +119,23 @@ namespace backend {
InputStateBuilder* DeviceBase::CreateInputStateBuilder() { InputStateBuilder* DeviceBase::CreateInputStateBuilder() {
return new InputStateBuilder(this); return new InputStateBuilder(this);
} }
PipelineLayoutBuilder* DeviceBase::CreatePipelineLayoutBuilder() { PipelineLayoutBase* DeviceBase::CreatePipelineLayout(
return new PipelineLayoutBuilder(this); const nxt::PipelineLayoutDescriptor* descriptor) {
MaybeError validation = ValidatePipelineLayoutDescriptor(this, descriptor);
if (validation.IsError()) {
// TODO(cwallez@chromium.org): Implement the WebGPU error handling mechanism.
delete validation.AcquireError();
return nullptr;
}
ResultOrError<PipelineLayoutBase*> maybePipelineLayout =
CreatePipelineLayoutImpl(descriptor);
if (maybePipelineLayout.IsError()) {
// TODO(cwallez@chromium.org): Implement the WebGPU error handling mechanism.
delete maybePipelineLayout.AcquireError();
return nullptr;
}
return maybePipelineLayout.AcquireSuccess();
} }
QueueBase* DeviceBase::CreateQueue() { QueueBase* DeviceBase::CreateQueue() {
ResultOrError<QueueBase*> maybeQueue = CreateQueueImpl(); ResultOrError<QueueBase*> maybeQueue = CreateQueueImpl();

View File

@ -45,7 +45,6 @@ namespace backend {
virtual DepthStencilStateBase* CreateDepthStencilState( virtual DepthStencilStateBase* CreateDepthStencilState(
DepthStencilStateBuilder* builder) = 0; DepthStencilStateBuilder* builder) = 0;
virtual InputStateBase* CreateInputState(InputStateBuilder* builder) = 0; virtual InputStateBase* CreateInputState(InputStateBuilder* builder) = 0;
virtual PipelineLayoutBase* CreatePipelineLayout(PipelineLayoutBuilder* builder) = 0;
virtual RenderPassDescriptorBase* CreateRenderPassDescriptor( virtual RenderPassDescriptorBase* CreateRenderPassDescriptor(
RenderPassDescriptorBuilder* builder) = 0; RenderPassDescriptorBuilder* builder) = 0;
virtual RenderPipelineBase* CreateRenderPipeline(RenderPipelineBuilder* builder) = 0; virtual RenderPipelineBase* CreateRenderPipeline(RenderPipelineBuilder* builder) = 0;
@ -83,7 +82,7 @@ namespace backend {
ComputePipelineBuilder* CreateComputePipelineBuilder(); ComputePipelineBuilder* CreateComputePipelineBuilder();
DepthStencilStateBuilder* CreateDepthStencilStateBuilder(); DepthStencilStateBuilder* CreateDepthStencilStateBuilder();
InputStateBuilder* CreateInputStateBuilder(); InputStateBuilder* CreateInputStateBuilder();
PipelineLayoutBuilder* CreatePipelineLayoutBuilder(); PipelineLayoutBase* CreatePipelineLayout(const nxt::PipelineLayoutDescriptor* descriptor);
QueueBase* CreateQueue(); QueueBase* CreateQueue();
RenderPassDescriptorBuilder* CreateRenderPassDescriptorBuilder(); RenderPassDescriptorBuilder* CreateRenderPassDescriptorBuilder();
RenderPipelineBuilder* CreateRenderPipelineBuilder(); RenderPipelineBuilder* CreateRenderPipelineBuilder();
@ -98,6 +97,8 @@ namespace backend {
void Release(); void Release();
private: private:
virtual ResultOrError<PipelineLayoutBase*> CreatePipelineLayoutImpl(
const nxt::PipelineLayoutDescriptor* descriptor) = 0;
virtual ResultOrError<QueueBase*> CreateQueueImpl() = 0; virtual ResultOrError<QueueBase*> CreateQueueImpl() = 0;
virtual ResultOrError<SamplerBase*> CreateSamplerImpl( virtual ResultOrError<SamplerBase*> CreateSamplerImpl(
const nxt::SamplerDescriptor* descriptor) = 0; const nxt::SamplerDescriptor* descriptor) = 0;

View File

@ -36,7 +36,15 @@ namespace backend {
// //
// Returning an error is done via: // Returning an error is done via:
// NXT_RETURN_ERROR("My error message"); // NXT_RETURN_ERROR("My error message");
#define NXT_RETURN_ERROR(EXPR) return MakeError(EXPR, __FILE__, __func__, __LINE__) #define NXT_RETURN_ERROR(MESSAGE) return MakeError(MESSAGE, __FILE__, __func__, __LINE__)
#define NXT_TRY_ASSERT(EXPR, MESSAGE) \
{ \
if (!(EXPR)) { \
NXT_RETURN_ERROR(MESSAGE); \
} \
} \
for (;;) \
break
#define NXT_CONCAT1(x, y) x##y #define NXT_CONCAT1(x, y) x##y
#define NXT_CONCAT2(x, y) NXT_CONCAT1(x, y) #define NXT_CONCAT2(x, y) NXT_CONCAT1(x, y)

View File

@ -27,10 +27,10 @@ namespace backend {
PipelineBase::PipelineBase(PipelineBuilder* builder) PipelineBase::PipelineBase(PipelineBuilder* builder)
: mStageMask(builder->mStageMask), mLayout(std::move(builder->mLayout)) { : mStageMask(builder->mStageMask), mLayout(std::move(builder->mLayout)) {
if (!mLayout) { if (!mLayout) {
mLayout = builder->GetParentBuilder() nxt::PipelineLayoutDescriptor descriptor;
->GetDevice() descriptor.numBindGroupLayouts = 0;
->CreatePipelineLayoutBuilder() descriptor.bindGroupLayouts = nullptr;
->GetResult(); mLayout = builder->GetParentBuilder()->GetDevice()->CreatePipelineLayout(&descriptor);
// Remove the external ref objects are created with // Remove the external ref objects are created with
mLayout->Release(); mLayout->Release();
} }

View File

@ -20,10 +20,37 @@
namespace backend { namespace backend {
MaybeError ValidatePipelineLayoutDescriptor(DeviceBase*,
const nxt::PipelineLayoutDescriptor* descriptor) {
NXT_TRY_ASSERT(descriptor->nextInChain == nullptr, "nextInChain must be nullptr");
NXT_TRY_ASSERT(descriptor->numBindGroupLayouts <= kMaxBindGroups,
"too many bind group layouts");
for (uint32_t i = 0; i < descriptor->numBindGroupLayouts; ++i) {
NXT_TRY_ASSERT(descriptor->bindGroupLayouts[i].Get() != nullptr,
"bind group layouts may not be null");
}
return {};
}
// PipelineLayoutBase // PipelineLayoutBase
PipelineLayoutBase::PipelineLayoutBase(PipelineLayoutBuilder* builder) PipelineLayoutBase::PipelineLayoutBase(DeviceBase* device,
: mBindGroupLayouts(std::move(builder->mBindGroupLayouts)), mMask(builder->mMask) { const nxt::PipelineLayoutDescriptor* descriptor) {
ASSERT(descriptor->numBindGroupLayouts <= kMaxBindGroups);
for (uint32_t group = 0; group < descriptor->numBindGroupLayouts; ++group) {
mBindGroupLayouts[group] =
reinterpret_cast<BindGroupLayoutBase*>(descriptor->bindGroupLayouts[group].Get());
mMask.set(group);
}
// TODO(kainino@chromium.org): It shouldn't be necessary to construct default bind
// group layouts here. Remove these and fix things so that they are not needed.
for (uint32_t group = descriptor->numBindGroupLayouts; group < kMaxBindGroups; ++group) {
auto builder = device->CreateBindGroupLayoutBuilder();
mBindGroupLayouts[group] = builder->GetResult();
// Remove the external ref objects are created with
mBindGroupLayouts[group]->Release();
builder->Release();
}
} }
const BindGroupLayoutBase* PipelineLayoutBase::GetBindGroupLayout(size_t group) const { const BindGroupLayoutBase* PipelineLayoutBase::GetBindGroupLayout(size_t group) const {
@ -49,40 +76,4 @@ namespace backend {
return kMaxBindGroups + 1; return kMaxBindGroups + 1;
} }
// PipelineLayoutBuilder
PipelineLayoutBuilder::PipelineLayoutBuilder(DeviceBase* device) : Builder(device) {
}
PipelineLayoutBase* PipelineLayoutBuilder::GetResultImpl() {
// 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
for (size_t group = 0; group < kMaxBindGroups; ++group) {
if (!mBindGroupLayouts[group]) {
auto builder = mDevice->CreateBindGroupLayoutBuilder();
mBindGroupLayouts[group] = builder->GetResult();
// Remove the external ref objects are created with
mBindGroupLayouts[group]->Release();
builder->Release();
}
}
return mDevice->CreatePipelineLayout(this);
}
void PipelineLayoutBuilder::SetBindGroupLayout(uint32_t groupIndex,
BindGroupLayoutBase* layout) {
if (groupIndex >= kMaxBindGroups) {
HandleError("groupIndex is over the maximum allowed");
return;
}
if (mMask[groupIndex]) {
HandleError("Bind group layout already specified");
return;
}
mBindGroupLayouts[groupIndex] = layout;
mMask.set(groupIndex);
}
} // namespace backend } // namespace backend

View File

@ -15,7 +15,7 @@
#ifndef BACKEND_PIPELINELAYOUT_H_ #ifndef BACKEND_PIPELINELAYOUT_H_
#define BACKEND_PIPELINELAYOUT_H_ #define BACKEND_PIPELINELAYOUT_H_
#include "backend/Builder.h" #include "backend/Error.h"
#include "backend/Forward.h" #include "backend/Forward.h"
#include "backend/RefCounted.h" #include "backend/RefCounted.h"
#include "common/Constants.h" #include "common/Constants.h"
@ -27,11 +27,14 @@
namespace backend { namespace backend {
MaybeError ValidatePipelineLayoutDescriptor(DeviceBase*,
const nxt::PipelineLayoutDescriptor* descriptor);
using BindGroupLayoutArray = std::array<Ref<BindGroupLayoutBase>, kMaxBindGroups>; using BindGroupLayoutArray = std::array<Ref<BindGroupLayoutBase>, kMaxBindGroups>;
class PipelineLayoutBase : public RefCounted { class PipelineLayoutBase : public RefCounted {
public: public:
PipelineLayoutBase(PipelineLayoutBuilder* builder); PipelineLayoutBase(DeviceBase* device, const nxt::PipelineLayoutDescriptor* descriptor);
const BindGroupLayoutBase* GetBindGroupLayout(size_t group) const; const BindGroupLayoutBase* GetBindGroupLayout(size_t group) const;
const std::bitset<kMaxBindGroups> GetBindGroupsLayoutMask() const; const std::bitset<kMaxBindGroups> GetBindGroupsLayoutMask() const;
@ -49,22 +52,6 @@ namespace backend {
std::bitset<kMaxBindGroups> mMask; std::bitset<kMaxBindGroups> mMask;
}; };
class PipelineLayoutBuilder : public Builder<PipelineLayoutBase> {
public:
PipelineLayoutBuilder(DeviceBase* device);
// NXT API
void SetBindGroupLayout(uint32_t groupIndex, BindGroupLayoutBase* layout);
private:
friend class PipelineLayoutBase;
PipelineLayoutBase* GetResultImpl() override;
BindGroupLayoutArray mBindGroupLayouts;
std::bitset<kMaxBindGroups> mMask;
};
} // namespace backend } // namespace backend
#endif // BACKEND_PIPELINELAYOUT_H_ #endif // BACKEND_PIPELINELAYOUT_H_

View File

@ -20,16 +20,13 @@
namespace backend { namespace backend {
MaybeError ValidateSamplerDescriptor(DeviceBase*, const nxt::SamplerDescriptor* descriptor) { MaybeError ValidateSamplerDescriptor(DeviceBase*, const nxt::SamplerDescriptor* descriptor) {
NXT_TRY_ASSERT(descriptor->nextInChain == nullptr, "nextInChain must be nullptr");
NXT_TRY(ValidateFilterMode(descriptor->minFilter)); NXT_TRY(ValidateFilterMode(descriptor->minFilter));
NXT_TRY(ValidateFilterMode(descriptor->magFilter)); NXT_TRY(ValidateFilterMode(descriptor->magFilter));
NXT_TRY(ValidateFilterMode(descriptor->mipmapFilter)); NXT_TRY(ValidateFilterMode(descriptor->mipmapFilter));
NXT_TRY(ValidateAddressMode(descriptor->addressModeU)); NXT_TRY(ValidateAddressMode(descriptor->addressModeU));
NXT_TRY(ValidateAddressMode(descriptor->addressModeV)); NXT_TRY(ValidateAddressMode(descriptor->addressModeV));
NXT_TRY(ValidateAddressMode(descriptor->addressModeW)); NXT_TRY(ValidateAddressMode(descriptor->addressModeW));
if (descriptor->nextInChain != nullptr) {
NXT_RETURN_ERROR("nextInChain must be nullptr");
}
return {}; return {};
} }

View File

@ -285,8 +285,9 @@ namespace backend { namespace d3d12 {
InputStateBase* Device::CreateInputState(InputStateBuilder* builder) { InputStateBase* Device::CreateInputState(InputStateBuilder* builder) {
return new InputState(this, builder); return new InputState(this, builder);
} }
PipelineLayoutBase* Device::CreatePipelineLayout(PipelineLayoutBuilder* builder) { ResultOrError<PipelineLayoutBase*> Device::CreatePipelineLayoutImpl(
return new PipelineLayout(this, builder); const nxt::PipelineLayoutDescriptor* descriptor) {
return new PipelineLayout(this, descriptor);
} }
ResultOrError<QueueBase*> Device::CreateQueueImpl() { ResultOrError<QueueBase*> Device::CreateQueueImpl() {
return new Queue(this); return new Queue(this);

View File

@ -47,7 +47,6 @@ namespace backend { namespace d3d12 {
ComputePipelineBase* CreateComputePipeline(ComputePipelineBuilder* builder) override; ComputePipelineBase* CreateComputePipeline(ComputePipelineBuilder* builder) override;
DepthStencilStateBase* CreateDepthStencilState(DepthStencilStateBuilder* builder) override; DepthStencilStateBase* CreateDepthStencilState(DepthStencilStateBuilder* builder) override;
InputStateBase* CreateInputState(InputStateBuilder* builder) override; InputStateBase* CreateInputState(InputStateBuilder* builder) override;
PipelineLayoutBase* CreatePipelineLayout(PipelineLayoutBuilder* builder) override;
RenderPassDescriptorBase* CreateRenderPassDescriptor( RenderPassDescriptorBase* CreateRenderPassDescriptor(
RenderPassDescriptorBuilder* builder) override; RenderPassDescriptorBuilder* builder) override;
RenderPipelineBase* CreateRenderPipeline(RenderPipelineBuilder* builder) override; RenderPipelineBase* CreateRenderPipeline(RenderPipelineBuilder* builder) override;
@ -79,6 +78,8 @@ namespace backend { namespace d3d12 {
void ExecuteCommandLists(std::initializer_list<ID3D12CommandList*> commandLists); void ExecuteCommandLists(std::initializer_list<ID3D12CommandList*> commandLists);
private: private:
ResultOrError<PipelineLayoutBase*> CreatePipelineLayoutImpl(
const nxt::PipelineLayoutDescriptor* descriptor) override;
ResultOrError<QueueBase*> CreateQueueImpl() override; ResultOrError<QueueBase*> CreateQueueImpl() override;
ResultOrError<SamplerBase*> CreateSamplerImpl( ResultOrError<SamplerBase*> CreateSamplerImpl(
const nxt::SamplerDescriptor* descriptor) override; const nxt::SamplerDescriptor* descriptor) override;

View File

@ -22,8 +22,8 @@ using Microsoft::WRL::ComPtr;
namespace backend { namespace d3d12 { namespace backend { namespace d3d12 {
PipelineLayout::PipelineLayout(Device* device, PipelineLayoutBuilder* builder) PipelineLayout::PipelineLayout(Device* device, const nxt::PipelineLayoutDescriptor* descriptor)
: PipelineLayoutBase(builder), mDevice(device) { : PipelineLayoutBase(device, descriptor) {
D3D12_ROOT_PARAMETER rootParameters[kMaxBindGroups * 2]; D3D12_ROOT_PARAMETER rootParameters[kMaxBindGroups * 2];
// A root parameter is one of these types // A root parameter is one of these types

View File

@ -25,7 +25,7 @@ namespace backend { namespace d3d12 {
class PipelineLayout : public PipelineLayoutBase { class PipelineLayout : public PipelineLayoutBase {
public: public:
PipelineLayout(Device* device, PipelineLayoutBuilder* builder); PipelineLayout(Device* device, const nxt::PipelineLayoutDescriptor* descriptor);
uint32_t GetCbvUavSrvRootParameterIndex(uint32_t group) const; uint32_t GetCbvUavSrvRootParameterIndex(uint32_t group) const;
uint32_t GetSamplerRootParameterIndex(uint32_t group) const; uint32_t GetSamplerRootParameterIndex(uint32_t group) const;
@ -33,8 +33,6 @@ namespace backend { namespace d3d12 {
ComPtr<ID3D12RootSignature> GetRootSignature(); ComPtr<ID3D12RootSignature> GetRootSignature();
private: private:
Device* mDevice;
std::array<uint32_t, kMaxBindGroups> mCbvUavSrvRootParameterInfo; std::array<uint32_t, kMaxBindGroups> mCbvUavSrvRootParameterInfo;
std::array<uint32_t, kMaxBindGroups> mSamplerRootParameterInfo; std::array<uint32_t, kMaxBindGroups> mSamplerRootParameterInfo;

View File

@ -44,7 +44,6 @@ namespace backend { namespace metal {
ComputePipelineBase* CreateComputePipeline(ComputePipelineBuilder* builder) override; ComputePipelineBase* CreateComputePipeline(ComputePipelineBuilder* builder) override;
DepthStencilStateBase* CreateDepthStencilState(DepthStencilStateBuilder* builder) override; DepthStencilStateBase* CreateDepthStencilState(DepthStencilStateBuilder* builder) override;
InputStateBase* CreateInputState(InputStateBuilder* builder) override; InputStateBase* CreateInputState(InputStateBuilder* builder) override;
PipelineLayoutBase* CreatePipelineLayout(PipelineLayoutBuilder* builder) override;
RenderPassDescriptorBase* CreateRenderPassDescriptor( RenderPassDescriptorBase* CreateRenderPassDescriptor(
RenderPassDescriptorBuilder* builder) override; RenderPassDescriptorBuilder* builder) override;
RenderPipelineBase* CreateRenderPipeline(RenderPipelineBuilder* builder) override; RenderPipelineBase* CreateRenderPipeline(RenderPipelineBuilder* builder) override;
@ -65,6 +64,8 @@ namespace backend { namespace metal {
ResourceUploader* GetResourceUploader() const; ResourceUploader* GetResourceUploader() const;
private: private:
ResultOrError<PipelineLayoutBase*> CreatePipelineLayoutImpl(
const nxt::PipelineLayoutDescriptor* descriptor) override;
ResultOrError<QueueBase*> CreateQueueImpl() override; ResultOrError<QueueBase*> CreateQueueImpl() override;
ResultOrError<SamplerBase*> CreateSamplerImpl( ResultOrError<SamplerBase*> CreateSamplerImpl(
const nxt::SamplerDescriptor* descriptor) override; const nxt::SamplerDescriptor* descriptor) override;

View File

@ -108,8 +108,9 @@ namespace backend { namespace metal {
InputStateBase* Device::CreateInputState(InputStateBuilder* builder) { InputStateBase* Device::CreateInputState(InputStateBuilder* builder) {
return new InputState(builder); return new InputState(builder);
} }
PipelineLayoutBase* Device::CreatePipelineLayout(PipelineLayoutBuilder* builder) { ResultOrError<PipelineLayoutBase*> Device::CreatePipelineLayoutImpl(
return new PipelineLayout(builder); const nxt::PipelineLayoutDescriptor* descriptor) {
return new PipelineLayout(this, descriptor);
} }
RenderPassDescriptorBase* Device::CreateRenderPassDescriptor( RenderPassDescriptorBase* Device::CreateRenderPassDescriptor(
RenderPassDescriptorBuilder* builder) { RenderPassDescriptorBuilder* builder) {

View File

@ -27,9 +27,11 @@ namespace spirv_cross {
namespace backend { namespace metal { namespace backend { namespace metal {
class Device;
class PipelineLayout : public PipelineLayoutBase { class PipelineLayout : public PipelineLayoutBase {
public: public:
PipelineLayout(PipelineLayoutBuilder* builder); PipelineLayout(Device* device, const nxt::PipelineLayoutDescriptor* descriptor);
using BindingIndexInfo = using BindingIndexInfo =
std::array<std::array<uint32_t, kMaxBindingsPerGroup>, kMaxBindGroups>; std::array<std::array<uint32_t, kMaxBindingsPerGroup>, kMaxBindGroups>;

View File

@ -15,10 +15,12 @@
#include "backend/metal/PipelineLayoutMTL.h" #include "backend/metal/PipelineLayoutMTL.h"
#include "backend/BindGroupLayout.h" #include "backend/BindGroupLayout.h"
#include "backend/metal/DeviceMTL.h"
namespace backend { namespace metal { namespace backend { namespace metal {
PipelineLayout::PipelineLayout(PipelineLayoutBuilder* builder) : PipelineLayoutBase(builder) { PipelineLayout::PipelineLayout(Device* device, const nxt::PipelineLayoutDescriptor* descriptor)
: PipelineLayoutBase(device, descriptor) {
// Each stage has its own numbering namespace in CompilerMSL. // Each stage has its own numbering namespace in CompilerMSL.
for (auto stage : IterateStages(kAllStages)) { for (auto stage : IterateStages(kAllStages)) {
// Buffer number 0 is reserved for push constants // Buffer number 0 is reserved for push constants

View File

@ -63,8 +63,9 @@ namespace backend { namespace null {
InputStateBase* Device::CreateInputState(InputStateBuilder* builder) { InputStateBase* Device::CreateInputState(InputStateBuilder* builder) {
return new InputState(builder); return new InputState(builder);
} }
PipelineLayoutBase* Device::CreatePipelineLayout(PipelineLayoutBuilder* builder) { ResultOrError<PipelineLayoutBase*> Device::CreatePipelineLayoutImpl(
return new PipelineLayout(builder); const nxt::PipelineLayoutDescriptor* descriptor) {
return new PipelineLayout(this, descriptor);
} }
ResultOrError<QueueBase*> Device::CreateQueueImpl() { ResultOrError<QueueBase*> Device::CreateQueueImpl() {
return new Queue(this); return new Queue(this);

View File

@ -104,7 +104,6 @@ namespace backend { namespace null {
ComputePipelineBase* CreateComputePipeline(ComputePipelineBuilder* builder) override; ComputePipelineBase* CreateComputePipeline(ComputePipelineBuilder* builder) override;
DepthStencilStateBase* CreateDepthStencilState(DepthStencilStateBuilder* builder) override; DepthStencilStateBase* CreateDepthStencilState(DepthStencilStateBuilder* builder) override;
InputStateBase* CreateInputState(InputStateBuilder* builder) override; InputStateBase* CreateInputState(InputStateBuilder* builder) override;
PipelineLayoutBase* CreatePipelineLayout(PipelineLayoutBuilder* builder) override;
RenderPassDescriptorBase* CreateRenderPassDescriptor( RenderPassDescriptorBase* CreateRenderPassDescriptor(
RenderPassDescriptorBuilder* builder) override; RenderPassDescriptorBuilder* builder) override;
RenderPipelineBase* CreateRenderPipeline(RenderPipelineBuilder* builder) override; RenderPipelineBase* CreateRenderPipeline(RenderPipelineBuilder* builder) override;
@ -119,6 +118,8 @@ namespace backend { namespace null {
std::vector<std::unique_ptr<PendingOperation>> AcquirePendingOperations(); std::vector<std::unique_ptr<PendingOperation>> AcquirePendingOperations();
private: private:
ResultOrError<PipelineLayoutBase*> CreatePipelineLayoutImpl(
const nxt::PipelineLayoutDescriptor* descriptor) override;
ResultOrError<QueueBase*> CreateQueueImpl() override; ResultOrError<QueueBase*> CreateQueueImpl() override;
ResultOrError<SamplerBase*> CreateSamplerImpl( ResultOrError<SamplerBase*> CreateSamplerImpl(
const nxt::SamplerDescriptor* descriptor) override; const nxt::SamplerDescriptor* descriptor) override;

View File

@ -77,8 +77,9 @@ namespace backend { namespace opengl {
InputStateBase* Device::CreateInputState(InputStateBuilder* builder) { InputStateBase* Device::CreateInputState(InputStateBuilder* builder) {
return new InputState(builder); return new InputState(builder);
} }
PipelineLayoutBase* Device::CreatePipelineLayout(PipelineLayoutBuilder* builder) { ResultOrError<PipelineLayoutBase*> Device::CreatePipelineLayoutImpl(
return new PipelineLayout(builder); const nxt::PipelineLayoutDescriptor* descriptor) {
return new PipelineLayout(this, descriptor);
} }
ResultOrError<QueueBase*> Device::CreateQueueImpl() { ResultOrError<QueueBase*> Device::CreateQueueImpl() {
return new Queue(this); return new Queue(this);

View File

@ -35,7 +35,6 @@ namespace backend { namespace opengl {
ComputePipelineBase* CreateComputePipeline(ComputePipelineBuilder* builder) override; ComputePipelineBase* CreateComputePipeline(ComputePipelineBuilder* builder) override;
DepthStencilStateBase* CreateDepthStencilState(DepthStencilStateBuilder* builder) override; DepthStencilStateBase* CreateDepthStencilState(DepthStencilStateBuilder* builder) override;
InputStateBase* CreateInputState(InputStateBuilder* builder) override; InputStateBase* CreateInputState(InputStateBuilder* builder) override;
PipelineLayoutBase* CreatePipelineLayout(PipelineLayoutBuilder* builder) override;
RenderPassDescriptorBase* CreateRenderPassDescriptor( RenderPassDescriptorBase* CreateRenderPassDescriptor(
RenderPassDescriptorBuilder* builder) override; RenderPassDescriptorBuilder* builder) override;
RenderPipelineBase* CreateRenderPipeline(RenderPipelineBuilder* builder) override; RenderPipelineBase* CreateRenderPipeline(RenderPipelineBuilder* builder) override;
@ -47,6 +46,8 @@ namespace backend { namespace opengl {
void TickImpl() override; void TickImpl() override;
private: private:
ResultOrError<PipelineLayoutBase*> CreatePipelineLayoutImpl(
const nxt::PipelineLayoutDescriptor* descriptor) override;
ResultOrError<QueueBase*> CreateQueueImpl() override; ResultOrError<QueueBase*> CreateQueueImpl() override;
ResultOrError<SamplerBase*> CreateSamplerImpl( ResultOrError<SamplerBase*> CreateSamplerImpl(
const nxt::SamplerDescriptor* descriptor) override; const nxt::SamplerDescriptor* descriptor) override;

View File

@ -15,10 +15,12 @@
#include "backend/opengl/PipelineLayoutGL.h" #include "backend/opengl/PipelineLayoutGL.h"
#include "backend/BindGroupLayout.h" #include "backend/BindGroupLayout.h"
#include "backend/opengl/DeviceGL.h"
namespace backend { namespace opengl { namespace backend { namespace opengl {
PipelineLayout::PipelineLayout(PipelineLayoutBuilder* builder) : PipelineLayoutBase(builder) { PipelineLayout::PipelineLayout(Device* device, const nxt::PipelineLayoutDescriptor* descriptor)
: PipelineLayoutBase(device, descriptor) {
GLuint uboIndex = 0; GLuint uboIndex = 0;
GLuint samplerIndex = 0; GLuint samplerIndex = 0;
GLuint sampledTextureIndex = 0; GLuint sampledTextureIndex = 0;

View File

@ -25,7 +25,7 @@ namespace backend { namespace opengl {
class PipelineLayout : public PipelineLayoutBase { class PipelineLayout : public PipelineLayoutBase {
public: public:
PipelineLayout(PipelineLayoutBuilder* builder); PipelineLayout(Device* device, const nxt::PipelineLayoutDescriptor* descriptor);
using BindingIndexInfo = using BindingIndexInfo =
std::array<std::array<GLuint, kMaxBindingsPerGroup>, kMaxBindGroups>; std::array<std::array<GLuint, kMaxBindingsPerGroup>, kMaxBindGroups>;

View File

@ -21,8 +21,6 @@
namespace backend { namespace opengl { namespace backend { namespace opengl {
class Device;
struct TextureFormatInfo { struct TextureFormatInfo {
GLenum internalFormat; GLenum internalFormat;
GLenum format; GLenum format;

View File

@ -241,8 +241,9 @@ namespace backend { namespace vulkan {
InputStateBase* Device::CreateInputState(InputStateBuilder* builder) { InputStateBase* Device::CreateInputState(InputStateBuilder* builder) {
return new InputState(builder); return new InputState(builder);
} }
PipelineLayoutBase* Device::CreatePipelineLayout(PipelineLayoutBuilder* builder) { ResultOrError<PipelineLayoutBase*> Device::CreatePipelineLayoutImpl(
return new PipelineLayout(builder); const nxt::PipelineLayoutDescriptor* descriptor) {
return new PipelineLayout(this, descriptor);
} }
ResultOrError<QueueBase*> Device::CreateQueueImpl() { ResultOrError<QueueBase*> Device::CreateQueueImpl() {
return new Queue(this); return new Queue(this);

View File

@ -72,7 +72,6 @@ namespace backend { namespace vulkan {
ComputePipelineBase* CreateComputePipeline(ComputePipelineBuilder* builder) override; ComputePipelineBase* CreateComputePipeline(ComputePipelineBuilder* builder) override;
DepthStencilStateBase* CreateDepthStencilState(DepthStencilStateBuilder* builder) override; DepthStencilStateBase* CreateDepthStencilState(DepthStencilStateBuilder* builder) override;
InputStateBase* CreateInputState(InputStateBuilder* builder) override; InputStateBase* CreateInputState(InputStateBuilder* builder) override;
PipelineLayoutBase* CreatePipelineLayout(PipelineLayoutBuilder* builder) override;
RenderPassDescriptorBase* CreateRenderPassDescriptor( RenderPassDescriptorBase* CreateRenderPassDescriptor(
RenderPassDescriptorBuilder* builder) override; RenderPassDescriptorBuilder* builder) override;
RenderPipelineBase* CreateRenderPipeline(RenderPipelineBuilder* builder) override; RenderPipelineBase* CreateRenderPipeline(RenderPipelineBuilder* builder) override;
@ -84,6 +83,8 @@ namespace backend { namespace vulkan {
void TickImpl() override; void TickImpl() override;
private: private:
ResultOrError<PipelineLayoutBase*> CreatePipelineLayoutImpl(
const nxt::PipelineLayoutDescriptor* descriptor) override;
ResultOrError<QueueBase*> CreateQueueImpl() override; ResultOrError<QueueBase*> CreateQueueImpl() override;
ResultOrError<SamplerBase*> CreateSamplerImpl( ResultOrError<SamplerBase*> CreateSamplerImpl(
const nxt::SamplerDescriptor* descriptor) override; const nxt::SamplerDescriptor* descriptor) override;

View File

@ -22,8 +22,8 @@
namespace backend { namespace vulkan { namespace backend { namespace vulkan {
PipelineLayout::PipelineLayout(PipelineLayoutBuilder* builder) PipelineLayout::PipelineLayout(Device* device, const nxt::PipelineLayoutDescriptor* descriptor)
: PipelineLayoutBase(builder), mDevice(ToBackend(builder->GetDevice())) { : PipelineLayoutBase(device, descriptor), mDevice(device) {
// Compute the array of VkDescriptorSetLayouts that will be chained in the create info. // Compute the array of VkDescriptorSetLayouts that will be chained in the create info.
// TODO(cwallez@chromium.org) Vulkan doesn't allow holes in this array, should we expose // TODO(cwallez@chromium.org) Vulkan doesn't allow holes in this array, should we expose
// this constraints at the NXT level? // this constraints at the NXT level?

View File

@ -25,7 +25,7 @@ namespace backend { namespace vulkan {
class PipelineLayout : public PipelineLayoutBase { class PipelineLayout : public PipelineLayoutBase {
public: public:
PipelineLayout(PipelineLayoutBuilder* builder); PipelineLayout(Device* device, const nxt::PipelineLayoutDescriptor* descriptor);
~PipelineLayout(); ~PipelineLayout();
VkPipelineLayout GetHandle() const; VkPipelineLayout GetHandle() const;

View File

@ -41,9 +41,7 @@ class BlendStateTest : public NXTTest {
.SetBindingsType(nxt::ShaderStageBit::Fragment, nxt::BindingType::UniformBuffer, 0, 1) .SetBindingsType(nxt::ShaderStageBit::Fragment, nxt::BindingType::UniformBuffer, 0, 1)
.GetResult(); .GetResult();
pipelineLayout = device.CreatePipelineLayoutBuilder() pipelineLayout = utils::MakeBasicPipelineLayout(device, &bindGroupLayout);
.SetBindGroupLayout(0, bindGroupLayout)
.GetResult();
renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize); renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize);
} }

View File

@ -82,9 +82,7 @@ class DepthStencilStateTest : public NXTTest {
.SetBindingsType(nxt::ShaderStageBit::Vertex | nxt::ShaderStageBit::Fragment, nxt::BindingType::UniformBuffer, 0, 1) .SetBindingsType(nxt::ShaderStageBit::Vertex | nxt::ShaderStageBit::Fragment, nxt::BindingType::UniformBuffer, 0, 1)
.GetResult(); .GetResult();
pipelineLayout = device.CreatePipelineLayoutBuilder() pipelineLayout = utils::MakeBasicPipelineLayout(device, &bindGroupLayout);
.SetBindGroupLayout(0, bindGroupLayout)
.GetResult();
} }
struct TestSpec { struct TestSpec {

View File

@ -49,9 +49,7 @@ class PushConstantTest: public NXTTest {
.SetBindingsType(kAllStages, nxt::BindingType::StorageBuffer, 0, extraBuffer ? 2 : 1) .SetBindingsType(kAllStages, nxt::BindingType::StorageBuffer, 0, extraBuffer ? 2 : 1)
.GetResult(); .GetResult();
nxt::PipelineLayout pl = device.CreatePipelineLayoutBuilder() nxt::PipelineLayout pl = utils::MakeBasicPipelineLayout(device, &bgl);
.SetBindGroupLayout(0, bgl)
.GetResult();
nxt::BufferView views[2] = { nxt::BufferView views[2] = {
buf1.CreateBufferViewBuilder().SetExtent(0, 4).GetResult(), buf1.CreateBufferViewBuilder().SetExtent(0, 4).GetResult(),
@ -155,7 +153,7 @@ class PushConstantTest: public NXTTest {
} }
nxt::PipelineLayout MakeEmptyLayout() { nxt::PipelineLayout MakeEmptyLayout() {
return device.CreatePipelineLayoutBuilder().GetResult(); return utils::MakeBasicPipelineLayout(device, nullptr);
} }
// The render pipeline adds one to the red channel for successful vertex push constant test // The render pipeline adds one to the red channel for successful vertex push constant test

View File

@ -28,8 +28,7 @@ class DrawQuad {
vsModule = utils::CreateShaderModule(*device, nxt::ShaderStage::Vertex, vsSource); vsModule = utils::CreateShaderModule(*device, nxt::ShaderStage::Vertex, vsSource);
fsModule = utils::CreateShaderModule(*device, nxt::ShaderStage::Fragment, fsSource); fsModule = utils::CreateShaderModule(*device, nxt::ShaderStage::Fragment, fsSource);
pipelineLayout = device->CreatePipelineLayoutBuilder() pipelineLayout = utils::MakeBasicPipelineLayout(*device, nullptr);
.GetResult();
} }
void Draw(nxt::CommandBufferBuilder* builder) { void Draw(nxt::CommandBufferBuilder* builder) {

View File

@ -48,9 +48,7 @@ protected:
.SetBindingsType(nxt::ShaderStageBit::Fragment, nxt::BindingType::SampledTexture, 1, 1) .SetBindingsType(nxt::ShaderStageBit::Fragment, nxt::BindingType::SampledTexture, 1, 1)
.GetResult(); .GetResult();
auto pipelineLayout = device.CreatePipelineLayoutBuilder() auto pipelineLayout = utils::MakeBasicPipelineLayout(device, &mBindGroupLayout);
.SetBindGroupLayout(0, mBindGroupLayout)
.GetResult();
auto vsModule = utils::CreateShaderModule(device, nxt::ShaderStage::Vertex, R"( auto vsModule = utils::CreateShaderModule(device, nxt::ShaderStage::Vertex, R"(
#version 450 #version 450

View File

@ -408,6 +408,34 @@ TEST_F(WireTests, StructureOfValuesArgument) {
FlushClient(); FlushClient();
} }
// Test that the wire is able to send structures that contain objects
TEST_F(WireTests, StructureOfObjectArrayArgument) {
nxtBindGroupLayoutBuilder bglBuilder = nxtDeviceCreateBindGroupLayoutBuilder(device);
nxtBindGroupLayout bgl = nxtBindGroupLayoutBuilderGetResult(bglBuilder);
nxtBindGroupLayoutBuilder apiBglBuilder = api.GetNewBindGroupLayoutBuilder();
EXPECT_CALL(api, DeviceCreateBindGroupLayoutBuilder(apiDevice))
.WillOnce(Return(apiBglBuilder));
nxtBindGroupLayout apiBgl = api.GetNewBindGroupLayout();
EXPECT_CALL(api, BindGroupLayoutBuilderGetResult(apiBglBuilder))
.WillOnce(Return(apiBgl));
nxtPipelineLayoutDescriptor descriptor;
descriptor.nextInChain = nullptr;
descriptor.numBindGroupLayouts = 1;
descriptor.bindGroupLayouts = &bgl;
nxtDeviceCreatePipelineLayout(device, &descriptor);
EXPECT_CALL(api, DeviceCreatePipelineLayout(apiDevice, MatchesLambda([apiBgl](const nxtPipelineLayoutDescriptor* desc) -> bool {
return desc->nextInChain == nullptr &&
desc->numBindGroupLayouts == 1 &&
desc->bindGroupLayouts[0] == apiBgl;
})))
.WillOnce(Return(nullptr));
FlushClient();
}
// Test that the server doesn't forward calls to error objects or with error objects // Test that the server doesn't forward calls to error objects or with error objects
// Also test that when GetResult is called on an error builder, the error callback is fired // Also test that when GetResult is called on an error builder, the error callback is fired
TEST_F(WireTests, CallsSkippedAfterBuilderError) { TEST_F(WireTests, CallsSkippedAfterBuilderError) {

View File

@ -24,7 +24,7 @@ class RenderPipelineValidationTest : public ValidationTest {
renderpass = CreateSimpleRenderPass(); renderpass = CreateSimpleRenderPass();
pipelineLayout = device.CreatePipelineLayoutBuilder().GetResult(); nxt::PipelineLayout pl = utils::MakeBasicPipelineLayout(device, nullptr);
inputState = device.CreateInputStateBuilder().GetResult(); inputState = device.CreateInputStateBuilder().GetResult();

View File

@ -149,5 +149,17 @@ namespace utils {
return desc; return desc;
} }
nxt::PipelineLayout MakeBasicPipelineLayout(const nxt::Device& device,
const nxt::BindGroupLayout* bindGroupLayout) {
nxt::PipelineLayoutDescriptor descriptor;
if (bindGroupLayout) {
descriptor.numBindGroupLayouts = 1;
descriptor.bindGroupLayouts = bindGroupLayout;
} else {
descriptor.numBindGroupLayouts = 0;
descriptor.bindGroupLayouts = nullptr;
}
return device.CreatePipelineLayout(&descriptor);
}
} // namespace utils } // namespace utils

View File

@ -49,5 +49,7 @@ namespace utils {
uint32_t height); uint32_t height);
nxt::SamplerDescriptor GetDefaultSamplerDescriptor(); nxt::SamplerDescriptor GetDefaultSamplerDescriptor();
nxt::PipelineLayout MakeBasicPipelineLayout(const nxt::Device& device,
const nxt::BindGroupLayout* bindGroupLayout);
} // namespace utils } // namespace utils