Skip to content
Closed
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
3 changes: 3 additions & 0 deletions Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,9 @@ class DeviceContextVkImpl final : public DeviceContextNextGenBase<EngineVkImplTr
__forceinline ResourceBindInfo& GetBindInfo(PIPELINE_TYPE Type);

__forceinline void CommitDescriptorSets(ResourceBindInfo& BindInfo, Uint32 CommitSRBMask);

void UpdateInlineConstantBuffers(ResourceBindInfo& BindInfo);

#ifdef DILIGENT_DEVELOPMENT
void DvpValidateCommittedShaderResources(ResourceBindInfo& BindInfo);
#endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ namespace Diligent

struct SPIRVShaderResourceAttribs;
class DeviceContextVkImpl;
class BufferVkImpl;

struct ImmutableSamplerAttribsVk
{
Expand All @@ -58,6 +59,17 @@ struct ImmutableSamplerAttribsVk
};
ASSERT_SIZEOF(ImmutableSamplerAttribsVk, 8, "The struct is used in serialization and must be tightly packed");

/// Inline constant buffer attributes for Vulkan backend.
/// Since Vulkan only supports one push constant block per pipeline, inline constants
/// are emulated using dynamic uniform buffers (similar to D3D11 backend).
struct InlineConstantBufferAttribsVk
{
Uint32 DescrSet = 0; // Descriptor set index
Uint32 BindingIndex = 0; // Binding index within the descriptor set
Uint32 NumConstants = 0; // Number of 32-bit constants
RefCntAutoPtr<BufferVkImpl> pBuffer; // Internal dynamic uniform buffer
};

struct PipelineResourceSignatureInternalDataVk : PipelineResourceSignatureInternalData<PipelineResourceAttribsVk, ImmutableSamplerAttribsVk>
{
Uint16 DynamicUniformBufferCount = 0;
Expand Down Expand Up @@ -134,6 +146,16 @@ class PipelineResourceSignatureVkImpl final : public PipelineResourceSignatureBa
void CommitDynamicResources(const ShaderResourceCacheVk& ResourceCache,
VkDescriptorSet vkDynamicDescriptorSet) const;

// Updates inline constant buffers by mapping the internal buffers and copying data from the resource cache
void UpdateInlineConstantBuffers(const ShaderResourceCacheVk& ResourceCache,
DeviceContextVkImpl& Ctx) const;

// Returns the number of inline constant buffers
Uint32 GetNumInlineConstantBuffers() const { return m_NumInlineConstantBuffers; }

// Returns the inline constant buffer attributes
const InlineConstantBufferAttribsVk* GetInlineConstantBuffers() const { return m_InlineConstantBuffers.get(); }

#ifdef DILIGENT_DEVELOPMENT
/// Verifies committed resource using the SPIRV resource attributes from the PSO.
bool DvpValidateCommittedResource(const DeviceContextVkImpl* pDeviceCtx,
Expand Down Expand Up @@ -193,6 +215,15 @@ class PipelineResourceSignatureVkImpl final : public PipelineResourceSignatureBa
// The total number storage buffers with dynamic offsets in both descriptor sets,
// accounting for array size.
Uint16 m_DynamicStorageBufferCount = 0;

// Number of inline constant buffers
Uint32 m_NumInlineConstantBuffers = 0;
// Inline constant buffer attributes
std::unique_ptr<InlineConstantBufferAttribsVk[]> m_InlineConstantBuffers;

// Pointer to CPU-side staging buffer for static inline constants
// This memory is allocated in CreateSetLayouts and must be freed in Destruct
void* m_pStaticInlineConstantData = nullptr;
};

template <> Uint32 PipelineResourceSignatureVkImpl::GetDescriptorSetIndex<PipelineResourceSignatureVkImpl::DESCRIPTOR_SET_ID_STATIC_MUTABLE>() const;
Expand Down
42 changes: 38 additions & 4 deletions Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ class ShaderResourceCacheVk : public ShaderResourceCacheBase
public:
explicit ShaderResourceCacheVk(ResourceCacheContentType ContentType) noexcept :
m_TotalResources{0},
m_ContentType{static_cast<Uint32>(ContentType)}
m_ContentType{static_cast<Uint32>(ContentType)},
m_HasInlineConstants{0}
{
VERIFY_EXPR(GetContentType() == ContentType);
}
Expand All @@ -93,7 +94,7 @@ class ShaderResourceCacheVk : public ShaderResourceCacheBase
void InitializeSets(IMemoryAllocator& MemAllocator, Uint32 NumSets, const Uint32* SetSizes);
void InitializeResources(Uint32 Set, Uint32 Offset, Uint32 ArraySize, DescriptorType Type, bool HasImmutableSampler);

// sizeof(Resource) == 32 (x64, msvc, Release)
// sizeof(Resource) == 40 (x64, msvc, Release)
struct Resource
{
explicit Resource(DescriptorType _Type, bool _HasImmutableSampler) noexcept :
Expand All @@ -120,6 +121,10 @@ class ShaderResourceCacheVk : public ShaderResourceCacheBase
/*16 */ Uint64 BufferBaseOffset = 0;
/*24 */ Uint64 BufferRangeSize = 0;

// For inline constants only - pointer to CPU-side staging buffer
/*32 */ void* pInlineConstantData = nullptr;
/*40 */ // End of structure

VkDescriptorBufferInfo GetUniformBufferDescriptorWriteInfo() const;
VkDescriptorBufferInfo GetStorageBufferDescriptorWriteInfo() const;
VkDescriptorImageInfo GetImageDescriptorWriteInfo () const;
Expand Down Expand Up @@ -245,13 +250,36 @@ class ShaderResourceCacheVk : public ShaderResourceCacheBase
Uint32 CacheOffset,
Uint32 DynamicBufferOffset);

// Sets inline constant data in the resource cache
void SetInlineConstants(Uint32 DescrSetIndex,
Uint32 CacheOffset,
const void* pConstants,
Uint32 FirstConstant,
Uint32 NumConstants);

// Gets the inline constant data pointer from the resource cache
const void* GetInlineConstantData(Uint32 DescrSetIndex, Uint32 BindingIndex) const;

// Initialize inline constant buffer in the resource cache
void InitializeInlineConstantBuffer(Uint32 DescrSetIndex,
Uint32 CacheOffset,
Uint32 NumConstants,
void* pInlineConstantData);

// Sets the inline constant memory block (takes ownership, will be freed in destructor)
void SetInlineConstantMemory(IMemoryAllocator& Allocator, void* pMemory)
{
m_pInlineConstantMemory = decltype(m_pInlineConstantMemory){
pMemory,
STDDeleter<void, IMemoryAllocator>(Allocator)};
}

Uint32 GetNumDescriptorSets() const { return m_NumSets; }
bool HasDynamicResources() const { return m_NumDynamicBuffers > 0; }

bool HasInlineConstants() const
{
return false;
return m_HasInlineConstants;
}

ResourceCacheContentType GetContentType() const { return static_cast<ResourceCacheContentType>(m_ContentType); }
Expand Down Expand Up @@ -287,16 +315,22 @@ class ShaderResourceCacheVk : public ShaderResourceCacheBase

std::unique_ptr<void, STDDeleter<void, IMemoryAllocator>> m_pMemory;

// Memory for inline constant data (allocated separately, freed in destructor)
std::unique_ptr<void, STDDeleter<void, IMemoryAllocator>> m_pInlineConstantMemory;

Uint16 m_NumSets = 0;

// Total actual number of dynamic buffers (that were created with USAGE_DYNAMIC) bound in the resource cache
// regardless of the variable type. Note this variable is not equal to dynamic offsets count, which is constant.
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 contains 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;
Expand Down
34 changes: 34 additions & 0 deletions Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,24 @@ DeviceContextVkImpl::ResourceBindInfo& DeviceContextVkImpl::GetBindInfo(PIPELINE
return m_BindInfo[Indices[Uint32{Type}]];
}

void DeviceContextVkImpl::UpdateInlineConstantBuffers(ResourceBindInfo& BindInfo)
{
const Uint32 SignCount = m_pPipelineState->GetResourceSignatureCount();
for (Uint32 i = 0; i < SignCount; ++i)
{
const PipelineResourceSignatureVkImpl* pSign = m_pPipelineState->GetResourceSignature(i);
if (pSign == nullptr || pSign->GetNumInlineConstantBuffers() == 0)
continue;

const ShaderResourceCacheVk* pResourceCache = BindInfo.ResourceCaches[i];
if (pResourceCache == nullptr || !pResourceCache->HasInlineConstants())
continue;

// Update inline constant buffers
pSign->UpdateInlineConstantBuffers(*pResourceCache, *this);
}
}

void DeviceContextVkImpl::CommitDescriptorSets(ResourceBindInfo& BindInfo, Uint32 CommitSRBMask)
{
VERIFY(CommitSRBMask != 0, "This method should not be called when there is nothing to commit");
Expand Down Expand Up @@ -758,6 +776,14 @@ void DeviceContextVkImpl::PrepareForDraw(DRAW_FLAGS Flags)
#endif

ResourceBindInfo& BindInfo = GetBindInfo(PIPELINE_TYPE_GRAPHICS);

// Update inline constant buffers before binding descriptor sets
const bool InlineConstantsIntact = (Flags & DRAW_FLAG_INLINE_CONSTANTS_INTACT) != 0;
if (!InlineConstantsIntact)
{
UpdateInlineConstantBuffers(BindInfo);
}

// First time we must always bind descriptor sets with dynamic offsets as SRBs are stale.
// If there are no dynamic buffers bound in the resource cache, for all subsequent
// calls we do not need to bind the sets again.
Expand Down Expand Up @@ -1059,6 +1085,10 @@ void DeviceContextVkImpl::PrepareForDispatchCompute()
EndRenderScope();

ResourceBindInfo& BindInfo = GetBindInfo(PIPELINE_TYPE_COMPUTE);

// Update inline constant buffers before binding descriptor sets
UpdateInlineConstantBuffers(BindInfo);

if (Uint32 CommitMask = BindInfo.GetCommitMask())
{
CommitDescriptorSets(BindInfo, CommitMask);
Expand All @@ -1075,6 +1105,10 @@ void DeviceContextVkImpl::PrepareForRayTracing()
EnsureVkCmdBuffer();

ResourceBindInfo& BindInfo = GetBindInfo(PIPELINE_TYPE_RAY_TRACING);

// Update inline constant buffers before binding descriptor sets
UpdateInlineConstantBuffers(BindInfo);

if (Uint32 CommitMask = BindInfo.GetCommitMask())
{
CommitDescriptorSets(BindInfo, CommitMask);
Expand Down
Loading
Loading