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
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2025 Diligent Graphics LLC
* Copyright 2019-2026 Diligent Graphics LLC
* Copyright 2015-2019 Egor Yusov
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -325,7 +325,7 @@ class DeviceContextGLImpl final : public DeviceContextBase<EngineGLImplTraits>
__forceinline void PostDraw();

using TBindings = PipelineResourceSignatureGLImpl::TBindings;
void BindProgramResources(Uint32 BindSRBMask);
void BindProgramResources(Uint32 BindSRBMask, bool DynamicBuffersIntact = false, bool InlineConstantsIntact = false);

#ifdef DILIGENT_DEVELOPMENT
void DvpValidateCommittedShaderResources();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2025 Diligent Graphics LLC
* Copyright 2019-2026 Diligent Graphics LLC
* Copyright 2015-2019 Egor Yusov
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -31,6 +31,7 @@
/// Declaration of Diligent::PipelineResourceSignatureGLImpl class

#include <array>
#include <memory>

#include "EngineGLImplTraits.hpp"
#include "PipelineResourceAttribsGL.hpp"
Expand Down Expand Up @@ -63,6 +64,19 @@ struct ImmutableSamplerAttribsGL
Uint32 Dummy = 0;
};

/// Attributes of an inline constant buffer in OpenGL.
/// OpenGL does not support push constants, so inline constants are emulated
/// using a shared dynamic UBO that is updated before each draw/dispatch.
struct InlineConstantBufferAttribsGL
{
Uint32 CacheOffset = 0; // UBO cache slot offset for this resource
Uint32 NumConstants = 0; // Number of 32-bit constants (from ResDesc.ArraySize)

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

struct PipelineResourceSignatureInternalDataGL : PipelineResourceSignatureInternalData<PipelineResourceAttribsGL, ImmutableSamplerAttribsGL>
{
PipelineResourceSignatureInternalDataGL() noexcept
Expand Down Expand Up @@ -127,6 +141,11 @@ class PipelineResourceSignatureGLImpl final : public PipelineResourceSignatureBa
// Make the base class method visible
using TPipelineResourceSignatureBase::CopyStaticResources;

// Updates inline constant buffers by mapping the shared dynamic UBOs and copying
// data from the CPU-side staging buffer in the resource cache.
void UpdateInlineConstantBuffers(const ShaderResourceCacheGL& ResourceCache,
class GLContextState& CtxState) const;

Uint32 GetImmutableSamplerIdx(const ResourceAttribs& Res) const
{
Uint32 ImtblSamIdx = InvalidImmutableSamplerIndex;
Expand All @@ -146,13 +165,28 @@ class PipelineResourceSignatureGLImpl final : public PipelineResourceSignatureBa
private:
void CreateLayout(bool IsSerialized);

const InlineConstantBufferAttribsGL& GetInlineConstantBuffer(Uint32 Index) const
{
VERIFY_EXPR(Index < m_NumInlineConstantBuffers);
return m_InlineConstantBuffers[Index];
}

private:
TBindings m_BindingCount = {};

// Indicates which UBO slots allow binding buffers with dynamic offsets
Uint64 m_DynamicUBOMask = 0;
// Indicates which SSBO slots allow binding buffers with dynamic offsets
Uint64 m_DynamicSSBOMask = 0;

// Number of inline constant buffers
Uint16 m_NumInlineConstantBuffers = 0;

// The total number of inline constants (32-bit values) in all inline constant buffers
Uint16 m_TotalInlineConstants = 0;

// Inline constant buffer attributes
std::unique_ptr<InlineConstantBufferAttribsGL[]> m_InlineConstantBuffers;
};

} // namespace Diligent
63 changes: 52 additions & 11 deletions Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2025 Diligent Graphics LLC
* Copyright 2019-2026 Diligent Graphics LLC
* Copyright 2015-2019 Egor Yusov
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -698,7 +698,7 @@ void DeviceContextGLImpl::DvpValidateCommittedShaderResources()
}
#endif

void DeviceContextGLImpl::BindProgramResources(Uint32 BindSRBMask)
void DeviceContextGLImpl::BindProgramResources(Uint32 BindSRBMask, bool DynamicBuffersIntact, bool InlineConstantsIntact)
{
VERIFY_EXPR(BindSRBMask != 0);
//if (m_CommittedResourcesTentativeBarriers != 0)
Expand All @@ -721,16 +721,55 @@ void DeviceContextGLImpl::BindProgramResources(Uint32 BindSRBMask)

const ShaderResourceCacheImplType* pResourceCache = m_BindInfo.ResourceCaches[sign];
DEV_CHECK_ERR(pResourceCache != nullptr, "Resource cache at index ", sign, " is null");
if (m_BindInfo.StaleSRBMask & SignBit)

const bool SRBStale = (m_BindInfo.StaleSRBMask & SignBit) != 0;
if (SRBStale)
{
pResourceCache->BindResources(GetContextState(), BaseBindings, m_BoundWritableTextures, m_BoundWritableBuffers);
}
else
{
VERIFY((m_BindInfo.DynamicSRBMask & SignBit) != 0,
"When bit in StaleSRBMask is not set, the same bit in DynamicSRBMask must be set. Check GetCommitMask().");
DEV_CHECK_ERR(pResourceCache->HasDynamicResources(),
"Bit in DynamicSRBMask is set, but the cache does not contain dynamic resources. This may indicate that resources "
"in the cache have changed, but the SRB has not been committed before the draw/dispatch command.");
pResourceCache->BindDynamicBuffers(GetContextState(), BaseBindings);
VERIFY(((m_BindInfo.DynamicSRBMask | m_BindInfo.InlineConstantsSRBMask) & SignBit) != 0,
"When bit in StaleSRBMask is not set, the same bit in either DynamicSRBMask or InlineConstantsSRBMask must be set. Check GetCommitMask().");

if ((m_BindInfo.DynamicSRBMask & SignBit) != 0)
{
DEV_CHECK_ERR(pResourceCache->HasDynamicResources(),
"Bit in DynamicSRBMask is set, but the cache does not contain dynamic resources. This may indicate that resources "
"in the cache have changed, but the SRB has not been committed before the draw/dispatch command.");
if (!DynamicBuffersIntact)
{
pResourceCache->BindDynamicBuffers(GetContextState(), BaseBindings);
}
}
}

// Update inline constant buffers if needed
if ((m_BindInfo.InlineConstantsSRBMask & SignBit) != 0)
{
VERIFY(pResourceCache->HasInlineConstants(),
"Shader resource cache does not contain inline constants, but the corresponding bit in InlineConstantsSRBMask is set. "
"This may be a bug because inline constants flag in the cache never changes after SRB creation, "
"while m_BindInfo.InlineConstantsSRBMask is initialized when SRB is committed.");
// Always update inline constant buffers if the SRB is stale
if (SRBStale || !InlineConstantsIntact)
{
if (PipelineResourceSignatureGLImpl* pSign = m_pPipelineState->GetResourceSignature(sign))
{
pSign->UpdateInlineConstantBuffers(*pResourceCache, GetContextState());
}
else
{
UNEXPECTED("Pipeline resource signature is null for signature index ", sign);
}
}
}
else
{
VERIFY(!pResourceCache->HasInlineConstants(),
"Shader resource cache contains inline constants, but the corresponding bit in InlineConstantsSRBMask is not set. "
"This may be a bug because inline constants flag in the cache never changes after SRB creation, "
"while m_BindInfo.InlineConstantsSRBMask is initialized when SRB is committed.");
}
}
m_BindInfo.StaleSRBMask &= ~m_BindInfo.ActiveSRBMask;
Expand Down Expand Up @@ -797,9 +836,11 @@ void DeviceContextGLImpl::PrepareForDraw(DRAW_FLAGS Flags, bool IsIndexed, GLenu
// The program might have changed since the last SetPipelineState call if a shader was
// created after the call (ShaderResourcesGL needs to bind a program to load uniforms).
m_pPipelineState->CommitProgram(m_ContextState);
if (Uint32 BindSRBMask = m_BindInfo.GetCommitMask(Flags & DRAW_FLAG_DYNAMIC_RESOURCE_BUFFERS_INTACT, Flags & DRAW_FLAG_INLINE_CONSTANTS_INTACT))
const bool DynamicBuffersIntact = (Flags & DRAW_FLAG_DYNAMIC_RESOURCE_BUFFERS_INTACT) != 0;
const bool InlineConstantsIntact = (Flags & DRAW_FLAG_INLINE_CONSTANTS_INTACT) != 0;
if (Uint32 BindSRBMask = m_BindInfo.GetCommitMask(DynamicBuffersIntact, InlineConstantsIntact))
{
BindProgramResources(BindSRBMask);
BindProgramResources(BindSRBMask, DynamicBuffersIntact, InlineConstantsIntact);
}

#ifdef DILIGENT_DEVELOPMENT
Expand Down
Loading
Loading