Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ class DeviceContextWebGPUImpl final : public DeviceContextBase<EngineWebGPUImplT
void CommitScissorRects(WGPURenderPassEncoder CmdEncoder);

template <typename CmdEncoderType>
void CommitBindGroups(CmdEncoderType CmdEncoder, Uint32 CommitSRBMask);
void CommitBindGroups(CmdEncoderType CmdEncoder, Uint32 CommitSRBMask, bool InlineConstantsIntact = false);

UploadMemoryManagerWebGPU::Allocation AllocateUploadMemory(size_t Size, size_t Alignment = 16);
DynamicMemoryManagerWebGPU::Allocation AllocateDynamicMemory(size_t Size, size_t Alignment = 16);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ namespace Diligent

struct WGSLShaderResourceAttribs;
class DeviceContextWebGPUImpl;
class BufferWebGPUImpl;

struct ImmutableSamplerAttribsWebGPU
{
Expand All @@ -65,9 +66,17 @@ struct ImmutableSamplerAttribsWebGPU
};
ASSERT_SIZEOF(ImmutableSamplerAttribsWebGPU, 16, "The struct is used in serialization and must be tightly packed");

/// Inline constant buffer attributes for WebGPU backend.
/// Similar to Vulkan's InlineConstantBufferAttribsVk.
struct InlineConstantBufferAttribsWebGPU
{
Uint8 Dummy = 0;
Uint32 BindGroup = 0; // Bind group index (similar to Vulkan's DescrSet)
Uint32 CacheOffset = 0; // Offset within bind group (similar to Vulkan's SRBCacheOffset)
Uint32 NumConstants = 0; // Number of 32-bit constants (= ResDesc.ArraySize)

// Shared dynamic UBO created in the Signature.
// All SRBs reference this same buffer to reduce memory usage.
RefCntAutoPtr<BufferWebGPUImpl> pBuffer;
};

struct PipelineResourceSignatureInternalDataWebGPU : PipelineResourceSignatureInternalData<PipelineResourceAttribsWebGPU, ImmutableSamplerAttribsWebGPU>
Expand Down Expand Up @@ -137,6 +146,11 @@ class PipelineResourceSignatureWebGPUImpl final : public PipelineResourceSignatu
// Make the base class method visible
using TPipelineResourceSignatureBase::CopyStaticResources;

// Updates inline constant buffers before draw/dispatch.
// Must be called when SRB is stale or DRAW_FLAG_INLINE_CONSTANTS_INTACT is not set.
void UpdateInlineConstantBuffers(const ShaderResourceCacheWebGPU& ResourceCache,
DeviceContextWebGPUImpl* pCtx) const;

// Returns the bind group index in the resource cache
template <BIND_GROUP_ID GroupId>
Uint32 GetBindGroupIndex() const;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,19 @@ class ShaderResourceCacheWebGPU : public ShaderResourceCacheBase

~ShaderResourceCacheWebGPU();

static size_t GetRequiredMemorySize(Uint32 NumGroups, const Uint32* GroupSizes);

void InitializeGroups(IMemoryAllocator& MemAllocator, Uint32 NumGroups, const Uint32* GroupSizes);
void InitializeResources(Uint32 GroupIdx, Uint32 Offset, Uint32 ArraySize, BindGroupEntryType Type, bool HasImmutableSampler);
static size_t GetRequiredMemorySize(Uint32 NumGroups, const Uint32* GroupSizes, Uint32 TotalInlineConstants = 0);

void InitializeGroups(IMemoryAllocator& MemAllocator, Uint32 NumGroups, const Uint32* GroupSizes, Uint32 TotalInlineConstants = 0);
void InitializeResources(Uint32 GroupIdx,
Uint32 Offset,
Uint32 ArraySize,
BindGroupEntryType Type,
bool HasImmutableSampler);
void InitializeInlineConstantBuffer(Uint32 GroupIdx,
Uint32 Offset,
Uint32 InlineConstantOffset,
Uint32 NumInlineConstants,
RefCntAutoPtr<IDeviceObject> pObject = {});

struct Resource
{
Expand All @@ -73,6 +82,14 @@ class ShaderResourceCacheWebGPU : public ShaderResourceCacheBase
"Immutable sampler can only be assigned to a textre or a sampler");
}

explicit Resource(BindGroupEntryType _Type, void* _pInlineConstantData = nullptr) noexcept :
Type{_Type},
HasImmutableSampler{false},
pInlineConstantData{_pInlineConstantData}
{
VERIFY(Type == BindGroupEntryType::UniformBufferDynamic, "Inline constant buffer must be of type UniformBufferDynamic");
}

// clang-format off
Resource (const Resource&) = delete;
Resource ( Resource&&) = delete;
Expand All @@ -88,11 +105,24 @@ class ShaderResourceCacheWebGPU : public ShaderResourceCacheBase
// For uniform and storage buffers only
/*16 */ Uint64 BufferBaseOffset = 0;
/*24 */ Uint64 BufferRangeSize = 0;
// For inline constant buffers only - pointer to the staging data
/*32 */ void* const pInlineConstantData = nullptr;
// clang-format on

void SetUniformBuffer(RefCntAutoPtr<IDeviceObject>&& _pBuffer, Uint64 _RangeOffset, Uint64 _RangeSize);
void SetStorageBuffer(RefCntAutoPtr<IDeviceObject>&& _pBufferView);

// Writes inline constant data to the staging buffer.
// IMPORTANT: Does NOT call UpdateRevision() - inline constants can change after SRB commit.
void SetInlineConstants(const void* pData, Uint32 FirstConstant, Uint32 NumConstants)
{
VERIFY(pInlineConstantData != nullptr, "Inline constant data pointer is not initialized");
VERIFY(pData != nullptr, "Source data is null");
VERIFY(FirstConstant + NumConstants <= BufferRangeSize / sizeof(Uint32),
"Too many constants (", FirstConstant + NumConstants, ") for the allocated space (", BufferRangeSize / sizeof(Uint32), ")");
memcpy(static_cast<Uint32*>(pInlineConstantData) + FirstConstant, pData, NumConstants * sizeof(Uint32));
}

template <typename ResType>
Uint32 GetDynamicBufferOffset(const DeviceContextWebGPUImpl* pCtx) const;

Expand Down Expand Up @@ -178,7 +208,7 @@ class ShaderResourceCacheWebGPU : public ShaderResourceCacheBase

bool HasInlineConstants() const
{
return false;
return m_HasInlineConstants != 0;
}

ResourceCacheContentType GetContentType() const { return static_cast<ResourceCacheContentType>(m_ContentType); }
Expand All @@ -190,6 +220,16 @@ class ShaderResourceCacheWebGPU : public ShaderResourceCacheBase
std::vector<uint32_t>& Offsets,
Uint32 GroupIdx) const;

// Writes inline constant data to the staging buffer
void SetInlineConstants(Uint32 BindGroupIdx, Uint32 CacheOffset, const void* pConstants, Uint32 FirstConstant, Uint32 NumConstants);

// Copies inline constant data from source cache to this cache
void CopyInlineConstants(const ShaderResourceCacheWebGPU& SrcCache,
Uint32 BindGroupIdx,
Uint32 SrcCacheOffset,
Uint32 DstCacheOffset,
Uint32 NumConstants);

#ifdef DILIGENT_DEBUG
// For debug purposes only
void DbgVerifyResourceInitialization() const;
Expand Down Expand Up @@ -221,6 +261,13 @@ class ShaderResourceCacheWebGPU : public ShaderResourceCacheBase
"WGPUBindGroupEntry storage exceeds allocated memory. This indicates a bug in memory calculation logic");
return pFirstWGPUEntry;
}
Uint32* GetInlineConstantDataPtr(Uint32 Offset = 0)
{
Uint32* pFirstInlineConstantData = AlignUpPtr(reinterpret_cast<Uint32*>(GetFirstWGPUEntryPtr() + m_TotalResources));
VERIFY(reinterpret_cast<Uint8*>(pFirstInlineConstantData + Offset) <= m_DbgMemoryEnd,
"Inline constant storage exceeds allocated memory. This indicates a bug in memory calculation logic");
return pFirstInlineConstantData + Offset;
}
BindGroup& GetBindGroup(Uint32 Index)
{
VERIFY_EXPR(Index < m_NumBindGroups);
Expand All @@ -235,14 +282,18 @@ class ShaderResourceCacheWebGPU : public ShaderResourceCacheBase
// The total actual number of dynamic buffers (that were created with USAGE_DYNAMIC) bound in the resource cache
// regardless of the variable type.
Uint16 m_NumDynamicBuffers = 0;
Uint32 m_TotalResources : 31;
Uint32 m_TotalResources : 30;

// Indicates what types of resources are stored in the cache
const Uint32 m_ContentType : 1;

// Indicates whether the cache has inline constants
Uint32 m_HasInlineConstants : 1;

#ifdef DILIGENT_DEBUG
// Debug array that stores flags indicating if resources in the cache have been initialized
std::vector<std::vector<bool>> m_DbgInitializedResources;
std::vector<bool> m_DbgAssignedInlineConstants;
Uint8* m_DbgMemoryEnd = nullptr;
#endif
};
Expand Down
25 changes: 21 additions & 4 deletions Graphics/GraphicsEngineWebGPU/src/DeviceContextWebGPUImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ void SetBindGroup(WGPUComputePassEncoder Encoder, uint32_t GroupIndex, WGPUBindG
}

template <typename CmdEncoderType>
void DeviceContextWebGPUImpl::CommitBindGroups(CmdEncoderType CmdEncoder, Uint32 CommitSRBMask)
void DeviceContextWebGPUImpl::CommitBindGroups(CmdEncoderType CmdEncoder, Uint32 CommitSRBMask, bool InlineConstantsIntact)
{
VERIFY(CommitSRBMask != 0, "This method should not be called when there is nothing to commit");

Expand All @@ -232,6 +232,25 @@ void DeviceContextWebGPUImpl::CommitBindGroups(CmdEncoderType CmdEncoder, Uint32
if ((CommitSRBMask & SRBBit) == 0)
continue;

const ShaderResourceCacheWebGPU* ResourceCache = m_BindInfo.ResourceCaches[sign];
VERIFY_EXPR(ResourceCache != nullptr);

// Update inline constant buffers if needed
const bool SRBStale = (m_BindInfo.StaleSRBMask & SRBBit) != 0;
if ((m_BindInfo.InlineConstantsSRBMask & SRBBit) != 0)
{
VERIFY(ResourceCache->HasInlineConstants(),
"Shader resource cache does not contain inline constants, but the corresponding bit in InlineConstantsSRBMask is set.");
// Update inline constant buffers if the SRB is stale or inline constants have changed
if (SRBStale || !InlineConstantsIntact)
{
if (PipelineResourceSignatureWebGPUImpl* pSign = m_pPipelineState->GetResourceSignature(sign))
{
pSign->UpdateInlineConstantBuffers(*ResourceCache, this);
}
}
}

Uint32 BindGroupCacheIndex = 0;
for (PipelineResourceSignatureWebGPUImpl::BIND_GROUP_ID BindGroupId : {PipelineResourceSignatureWebGPUImpl::BIND_GROUP_ID_STATIC_MUTABLE,
PipelineResourceSignatureWebGPUImpl::BIND_GROUP_ID_DYNAMIC})
Expand All @@ -240,16 +259,14 @@ void DeviceContextWebGPUImpl::CommitBindGroups(CmdEncoderType CmdEncoder, Uint32
if (!BindGroup.IsActive())
continue;

const ShaderResourceCacheWebGPU* ResourceCache = m_BindInfo.ResourceCaches[sign];
VERIFY_EXPR(ResourceCache != nullptr);
bool DynamicOffsetsChanged = false;
if (!BindGroup.DynamicBufferOffsets.empty())
{
DynamicOffsetsChanged = ResourceCache->GetDynamicBufferOffsets(this, BindGroup.DynamicBufferOffsets, BindGroupCacheIndex);
}
++BindGroupCacheIndex;

if ((m_BindInfo.StaleSRBMask & SRBBit) == 0 && !DynamicOffsetsChanged)
if (!SRBStale && !DynamicOffsetsChanged)
{
continue;
}
Expand Down
Loading
Loading