Skip to content

Commit cd10048

Browse files
WebGPU: moved dynamic buffer allocations to device context (#420)
1 parent 4afabf2 commit cd10048

9 files changed

+143
-138
lines changed

Graphics/GraphicsEngineWebGPU/include/BufferWebGPUImpl.hpp

Lines changed: 2 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -76,41 +76,12 @@ class BufferWebGPUImpl final : public BufferBase<EngineWebGPUImplTraits>, public
7676
/// Implementation of IBufferWebGPU::GetWebGPUBuffer().
7777
WGPUBuffer DILIGENT_CALL_TYPE GetWebGPUBuffer() const override final;
7878

79-
Uint64 GetDynamicOffset(DeviceContextIndex CtxId, const DeviceContextWebGPUImpl* pCtx) const
80-
{
81-
if (m_wgpuBuffer)
82-
{
83-
return 0;
84-
}
85-
else
86-
{
87-
VERIFY(m_Desc.Usage == USAGE_DYNAMIC, "Dynamic buffer is expected");
88-
VERIFY_EXPR(!m_DynamicAllocations.empty());
89-
#ifdef DILIGENT_DEVELOPMENT
90-
if (pCtx != nullptr)
91-
{
92-
DvpVerifyDynamicAllocation(pCtx);
93-
}
94-
#endif
95-
const DynamicMemoryManagerWebGPU::Allocation& DynAlloc = GetDynamicAllocation(CtxId);
96-
return DynAlloc.Offset;
97-
}
98-
}
99-
100-
#ifdef DILIGENT_DEVELOPMENT
101-
void DvpVerifyDynamicAllocation(const DeviceContextWebGPUImpl* pCtx) const;
102-
#endif
103-
10479
void* Map(MAP_TYPE MapType);
10580

10681
void Unmap();
10782

10883
Uint32 GetAlignment() const;
10984

110-
const DynamicMemoryManagerWebGPU::Allocation& GetDynamicAllocation(DeviceContextIndex CtxId) const;
111-
112-
void SetDynamicAllocation(DeviceContextIndex CtxId, DynamicMemoryManagerWebGPU::Allocation&& Allocation);
113-
11485
StagingBufferInfo* GetStagingBuffer();
11586

11687
private:
@@ -119,26 +90,10 @@ class BufferWebGPUImpl final : public BufferBase<EngineWebGPUImplTraits>, public
11990
private:
12091
friend class DeviceContextWebGPUImpl;
12192

122-
// Use 64-byte alignment to avoid cache issues
123-
static constexpr size_t CacheLineSize = 64;
124-
struct alignas(64) DynamicAllocation : DynamicMemoryManagerWebGPU::Allocation
125-
{
126-
DynamicAllocation& operator=(const Allocation& Allocation)
127-
{
128-
*static_cast<DynamicMemoryManagerWebGPU::Allocation*>(this) = Allocation;
129-
return *this;
130-
}
131-
Uint8 Padding[CacheLineSize - sizeof(Allocation)] = {};
132-
};
133-
static_assert(sizeof(DynamicAllocation) == CacheLineSize, "Unexpected sizeof(DynamicAllocation)");
134-
135-
using DynamicAllocationList = std::vector<DynamicAllocation, STDAllocatorRawMem<DynamicAllocation>>;
136-
13793
static constexpr Uint32 MaxStagingReadBuffers = 16;
13894

139-
WebGPUBufferWrapper m_wgpuBuffer;
140-
DynamicAllocationList m_DynamicAllocations;
141-
const Uint32 m_Alignment;
95+
WebGPUBufferWrapper m_wgpuBuffer;
96+
const Uint32 m_Alignment;
14297
};
14398

14499
} // namespace Diligent

Graphics/GraphicsEngineWebGPU/include/DeviceContextWebGPUImpl.hpp

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,13 @@ class DeviceContextWebGPUImpl final : public DeviceContextBase<EngineWebGPUImplT
310310

311311
Uint64 GetCompletedFenceValue();
312312

313+
#ifdef DILIGENT_DEVELOPMENT
314+
void DvpVerifyDynamicAllocation(const BufferWebGPUImpl* pBuffer) const;
315+
#endif
316+
317+
const DynamicMemoryManagerWebGPU::Allocation& GetDynamicBufferAllocation(const BufferWebGPUImpl* pBuffer) const;
318+
Uint64 GetDynamicBufferOffset(const BufferWebGPUImpl* pBuffer, bool VerifyAllocation = true) const;
319+
313320
private:
314321
enum COMMAND_ENCODER_FLAGS : Uint32
315322
{
@@ -565,12 +572,21 @@ class DeviceContextWebGPUImpl final : public DeviceContextBase<EngineWebGPUImplT
565572
UploadMemoryManagerWebGPU::Allocation Allocation;
566573
};
567574

575+
struct MappedBuffer
576+
{
577+
DynamicMemoryManagerWebGPU::Allocation Allocation;
578+
#ifdef DILIGENT_DEVELOPMENT
579+
UniqueIdentifier DvpBufferUID = -1;
580+
#endif
581+
};
582+
568583
using PendingFenceList = std::vector<std::pair<Uint64, RefCntAutoPtr<FenceWebGPUImpl>>>;
569584
using PendingQueryList = std::vector<PendingQuery>;
570585
using AttachmentClearList = std::vector<OptimizedClearValue>;
571586
using UploadMemoryPageList = std::vector<UploadMemoryManagerWebGPU::Page>;
572587
using DynamicMemoryPageList = std::vector<DynamicMemoryManagerWebGPU::Page>;
573-
using MappedTextureCache = std::unordered_map<MappedTextureKey, MappedTexture, MappedTextureKey::Hasher>;
588+
using MappedTexturesCache = std::unordered_map<MappedTextureKey, MappedTexture, MappedTextureKey::Hasher>;
589+
using MappedBuffersCache = std::vector<MappedBuffer>;
574590
using DebugGroupStack = std::vector<DEBUG_GROUP_TYPE>;
575591
using OcclusionQueryStack = std::vector<std::pair<OCCLUSION_QUERY_TYPE, Uint32>>;
576592
using PendingStagingResources = std::unordered_map<WebGPUResourceBase::StagingBufferInfo*, RefCntAutoPtr<IObject>>;
@@ -585,7 +601,8 @@ class DeviceContextWebGPUImpl final : public DeviceContextBase<EngineWebGPUImplT
585601
PendingQueryList m_PendingTimeQueries;
586602
UploadMemoryPageList m_UploadMemPages;
587603
DynamicMemoryPageList m_DynamicMemPages;
588-
MappedTextureCache m_MappedTextures;
604+
MappedTexturesCache m_MappedTextures;
605+
MappedBuffersCache m_MappedBuffers;
589606
DebugGroupStack m_DebugGroupsStack;
590607
DebugGroupStack m_PendingDebugGroups;
591608
OcclusionQueryStack m_OcclusionQueriesStack;

Graphics/GraphicsEngineWebGPU/include/ShaderResourceCacheWebGPU.hpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2023-2024 Diligent Graphics LLC
2+
* Copyright 2023-2025 Diligent Graphics LLC
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -42,6 +42,7 @@ namespace Diligent
4242
{
4343

4444
struct IMemoryAllocator;
45+
class DeviceContextWebGPUImpl;
4546

4647
class ShaderResourceCacheWebGPU : public ShaderResourceCacheBase
4748
{
@@ -93,7 +94,7 @@ class ShaderResourceCacheWebGPU : public ShaderResourceCacheBase
9394
void SetStorageBuffer(RefCntAutoPtr<IDeviceObject>&& _pBufferView);
9495

9596
template <typename ResType>
96-
Uint32 GetDynamicBufferOffset(DeviceContextIndex CtxId) const;
97+
Uint32 GetDynamicBufferOffset(const DeviceContextWebGPUImpl* pCtx) const;
9798

9899
explicit operator bool() const { return pObject != nullptr; }
99100
};
@@ -180,9 +181,9 @@ class ShaderResourceCacheWebGPU : public ShaderResourceCacheBase
180181
WGPUBindGroup UpdateBindGroup(WGPUDevice wgpuDevice, Uint32 GroupIndex, WGPUBindGroupLayout wgpuGroupLayout);
181182

182183
// Returns true if any dynamic offset has changed
183-
bool GetDynamicBufferOffsets(DeviceContextIndex CtxId,
184-
std::vector<uint32_t>& Offsets,
185-
Uint32 GroupIdx) const;
184+
bool GetDynamicBufferOffsets(const DeviceContextWebGPUImpl* pCtx,
185+
std::vector<uint32_t>& Offsets,
186+
Uint32 GroupIdx) const;
186187

187188
#ifdef DILIGENT_DEBUG
188189
// For debug purposes only

Graphics/GraphicsEngineWebGPU/src/AttachmentCleanerWebGPU.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2023-2024 Diligent Graphics LLC
2+
* Copyright 2023-2025 Diligent Graphics LLC
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -354,7 +354,7 @@ void AttachmentCleanerWebGPU::ClearAttachment(WGPURenderPassEncoder wgpuCmdEncod
354354
pDeviceContext->UnmapBuffer(m_pBuffer, MAP_WRITE);
355355

356356
const BufferWebGPUImpl* pBufferImpl = m_pBuffer.RawPtr<BufferWebGPUImpl>();
357-
const Uint32 DynamicOffsets[] = {static_cast<Uint32>(pBufferImpl->GetDynamicOffset(pDeviceContext->GetContextId(), nullptr))};
357+
const Uint32 DynamicOffsets[] = {static_cast<Uint32>(pDeviceContext->GetDynamicBufferOffset(pBufferImpl))};
358358

359359
wgpuRenderPassEncoderSetPipeline(wgpuCmdEncoder, wgpuPipelineState);
360360
wgpuRenderPassEncoderSetBindGroup(wgpuCmdEncoder, 0, m_PipelineResourceLayout.wgpuBindGroup, _countof(DynamicOffsets), DynamicOffsets);

Graphics/GraphicsEngineWebGPU/src/BufferWebGPUImpl.cpp

Lines changed: 6 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -57,19 +57,15 @@ BufferWebGPUImpl::BufferWebGPUImpl(IReferenceCounters* pRefCounters,
5757
const BufferDesc& Desc,
5858
const BufferData* pInitData,
5959
bool bIsDeviceInternal) :
60-
// clang-format off
61-
TBufferBase
62-
{
60+
TBufferBase{
6361
pRefCounters,
6462
BuffViewObjMemAllocator,
6563
pDevice,
6664
Desc,
67-
bIsDeviceInternal
65+
bIsDeviceInternal,
6866
},
69-
WebGPUResourceBase{*this, Desc.Usage == USAGE_STAGING ? ((Desc.CPUAccessFlags & CPU_ACCESS_READ) ? MaxStagingReadBuffers : 1): 0},
70-
m_DynamicAllocations(STD_ALLOCATOR_RAW_MEM(DynamicAllocation, GetRawAllocator(), "Allocator for vector<DynamicAllocation>")),
67+
WebGPUResourceBase{*this, Desc.Usage == USAGE_STAGING ? ((Desc.CPUAccessFlags & CPU_ACCESS_READ) ? MaxStagingReadBuffers : 1) : 0},
7168
m_Alignment{ComputeBufferAlignment(pDevice, m_Desc)}
72-
// clang-format on
7369
{
7470
ValidateBufferInitData(m_Desc, pInitData);
7571

@@ -82,12 +78,7 @@ BufferWebGPUImpl::BufferWebGPUImpl(IReferenceCounters* pRefCounters,
8278
const bool RequiresBackingBuffer = (m_Desc.BindFlags & BIND_UNORDERED_ACCESS) != 0 || ((m_Desc.BindFlags & BIND_SHADER_RESOURCE) != 0 && m_Desc.Mode == BUFFER_MODE_FORMATTED);
8379
const bool InitializeBuffer = (pInitData != nullptr && pInitData->pData != nullptr);
8480

85-
if (m_Desc.Usage == USAGE_DYNAMIC && !RequiresBackingBuffer)
86-
{
87-
size_t CtxCount = pDevice->GetNumImmediateContexts() + pDevice->GetNumDeferredContexts();
88-
m_DynamicAllocations.resize(CtxCount);
89-
}
90-
else
81+
if (m_Desc.Usage != USAGE_DYNAMIC || RequiresBackingBuffer)
9182
{
9283
if (m_Desc.Usage == USAGE_STAGING)
9384
{
@@ -156,20 +147,16 @@ BufferWebGPUImpl::BufferWebGPUImpl(IReferenceCounters* pRefCounters,
156147
RESOURCE_STATE InitialState,
157148
WGPUBuffer wgpuBuffer,
158149
bool bIsDeviceInternal) :
159-
// clang-format off
160-
TBufferBase
161-
{
150+
TBufferBase{
162151
pRefCounters,
163152
BuffViewObjMemAllocator,
164153
pDevice,
165154
Desc,
166-
bIsDeviceInternal
155+
bIsDeviceInternal,
167156
},
168157
WebGPUResourceBase{*this, 0},
169158
m_wgpuBuffer{wgpuBuffer, {true}},
170-
m_DynamicAllocations(STD_ALLOCATOR_RAW_MEM(DynamicAllocation, GetRawAllocator(), "Allocator for vector<DynamicAllocation>")),
171159
m_Alignment{ComputeBufferAlignment(pDevice, Desc)}
172-
// clang-format on
173160
{
174161
DEV_CHECK_ERR(Desc.Usage != USAGE_STAGING, "USAGE_STAGING buffer is not expected");
175162

@@ -215,16 +202,6 @@ Uint32 BufferWebGPUImpl::GetAlignment() const
215202
return m_Alignment;
216203
}
217204

218-
const DynamicMemoryManagerWebGPU::Allocation& BufferWebGPUImpl::GetDynamicAllocation(DeviceContextIndex CtxId) const
219-
{
220-
return m_DynamicAllocations[CtxId];
221-
}
222-
223-
void BufferWebGPUImpl::SetDynamicAllocation(DeviceContextIndex CtxId, DynamicMemoryManagerWebGPU::Allocation&& Allocation)
224-
{
225-
m_DynamicAllocations[CtxId] = std::move(Allocation);
226-
}
227-
228205
BufferWebGPUImpl::StagingBufferInfo* BufferWebGPUImpl::GetStagingBuffer()
229206
{
230207
VERIFY(m_Desc.Usage == USAGE_STAGING, "USAGE_STAGING buffer is expected");
@@ -262,21 +239,4 @@ void BufferWebGPUImpl::CreateViewInternal(const BufferViewDesc& OrigViewDesc, IB
262239
}
263240
}
264241

265-
266-
#ifdef DILIGENT_DEVELOPMENT
267-
void BufferWebGPUImpl::DvpVerifyDynamicAllocation(const DeviceContextWebGPUImpl* pCtx) const
268-
{
269-
if (!m_wgpuBuffer)
270-
{
271-
VERIFY(m_Desc.Usage == USAGE_DYNAMIC, "Dynamic buffer is expected");
272-
273-
const DeviceContextIndex ContextId = pCtx->GetContextId();
274-
const DynamicAllocation& DynAlloc = m_DynamicAllocations[ContextId];
275-
const Uint64 CurrentFrame = pCtx->GetFrameNumber();
276-
DEV_CHECK_ERR(DynAlloc, "Dynamic buffer '", m_Desc.Name, "' has not been mapped before its first use. Context Id: ", ContextId, ". Note: memory for dynamic buffers is allocated when a buffer is mapped.");
277-
DEV_CHECK_ERR(DynAlloc.dvpFrameNumber == CurrentFrame, "Dynamic allocation of dynamic buffer '", m_Desc.Name, "' in frame ", CurrentFrame, " is out-of-date. Note: contents of all dynamic resources is discarded at the end of every frame. A buffer must be mapped before its first use in any frame.");
278-
}
279-
}
280-
#endif
281-
282242
} // namespace Diligent

0 commit comments

Comments
 (0)