Files
Brandyn / Techy fcc1b09210 init
2026-04-04 15:40:51 -05:00

215 lines
5.3 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved..
/*=============================================================================
VulkanQueue.h: Private Vulkan RHI definitions.
=============================================================================*/
#pragma once
#include "VulkanConfiguration.h"
#include "VulkanBarriers.h"
#include "VulkanCommandBuffer.h"
#include "RHIDiagnosticBuffer.h"
#include "RHICoreNvidiaAftermath.h"
class FVulkanDynamicRHI;
class FVulkanDevice;
class FVulkanPayload;
class FVulkanTiming;
namespace VulkanRHI
{
class FFence;
class FSemaphore;
}
enum class EVulkanQueueType : uint8
{
Graphics = 0,
AsyncCompute,
Transfer,
Count,
};
inline const TCHAR* GetVulkanQueueTypeName(EVulkanQueueType QueueType)
{
switch (QueueType)
{
default: checkNoEntry(); // fallthrough
case EVulkanQueueType::Graphics: return TEXT("Graphics");
case EVulkanQueueType::AsyncCompute: return TEXT("AsyncCompute");
case EVulkanQueueType::Transfer: return TEXT("Transfer");
}
}
struct FBinarySemaphoreSignalInfo
{
uint64 TimelineValue;
EVulkanQueueType QueueType;
};
class FVulkanQueue
{
public:
FVulkanQueue(FVulkanDevice& InDevice, uint32 InFamilyIndex, EVulkanQueueType InQueueType);
~FVulkanQueue();
EVulkanQueueType GetQueueType()
{
return QueueType;
}
uint32 GetFamilyIndex() const
{
return FamilyIndex;
}
uint32 GetQueueIndex() const
{
return QueueIndex;
}
VkQueue GetHandle() const
{
return Queue;
}
FVulkanCommandBufferPool* AcquireCommandBufferPool(EVulkanCommandBufferType CommandBufferType);
void ReleaseCommandBufferPool(FVulkanCommandBufferPool* CommandBufferPool);
VkPipelineStageFlags GetSupportedStageBits() const
{
return SupportedStages;
}
VkAccessFlags GetSupportedAccessFlags() const
{
return SupportedAccess;
}
const FVulkanSemaphore* GetTimelineSemaphore() const
{
return TimelineSempahore;
}
uint64 GetLastSubmittedTimelineSemaphoreValue() const
{
return NextTimelineSemaphoreValue - 1;
}
uint64 GetCompletedTimelineSemaphoreValue() const
{
return CompletedTimelineSemaphoreValue;
}
void EnqueuePayload(FVulkanPayload* InPayload)
{
PendingSubmission.Enqueue(InPayload);
}
int32 SubmitQueuedPayloads(TMap<VkSemaphore, FBinarySemaphoreSignalInfo>& SignaledSemas);
int32 ProcessInterruptQueue(uint64 Timeout);
#if RHI_NEW_GPU_PROFILER
UE::RHI::GPUProfiler::FQueue GetProfilerQueue() const;
#endif
void InitDiagnosticBuffer();
class FVulkanDiagnosticBuffer* GetDiagnosticBuffer()
{
return DiagnosticBuffer.Get();
}
private:
void SubmitPayloads(TArrayView<FVulkanPayload*> Payloads, TMap<VkSemaphore, FBinarySemaphoreSignalInfo>& InOutSignaledSemas);
void Submit(TArrayView<VkSubmitInfo> InSubmitInfos, FVulkanFence* Fence);
void BindSparseResources(FVulkanPayload& Payload);
// Used by submission pipe which holds the proper locks to access this queue
FVulkanPayload* GetNextInterruptPayload()
{
FVulkanPayload* Payload = nullptr;
PendingInterrupt.Peek(Payload);
return Payload;
}
friend FVulkanDynamicRHI;
VkQueue Queue;
uint32 FamilyIndex;
uint32 QueueIndex;
EVulkanQueueType QueueType;
FVulkanDevice& Device;
FCriticalSection CommandBufferPoolCS;
TStaticArray<TArray<FVulkanCommandBufferPool*>, (int32)EVulkanCommandBufferType::Count> CommandBufferPools;
const bool bUseTimelineSemaphores;
FVulkanSemaphore* TimelineSempahore = nullptr;
uint64 NextTimelineSemaphoreValue = 1;
uint64 CompletedTimelineSemaphoreValue = 0;
uint64 SubmitCounter;
VkPipelineStageFlags SupportedStages = VK_PIPELINE_STAGE_NONE;
VkAccessFlags SupportedAccess = VK_ACCESS_NONE;
TQueue<FVulkanPayload*, EQueueMode::Mpsc> PendingSubmission;
TQueue<FVulkanPayload*, EQueueMode::Spsc> PendingInterrupt;
#if RHI_NEW_GPU_PROFILER
// The active timing struct on this queue. Updated / accessed by the interrupt thread.
FVulkanTiming* Timing = nullptr;
#endif
TUniquePtr<class FVulkanDiagnosticBuffer> DiagnosticBuffer;
void FillSupportedStageBits();
};
//
// Per Queue diagnostic buffer. Stays accessible after a GPU crash to allow readback of diagnostic messages.
// Also used to track the progress of the GPU via breadcrumb markers.
//
class FVulkanDiagnosticBuffer : public FRHIDiagnosticBuffer
{
public:
FVulkanDiagnosticBuffer(FVulkanDevice& InDevice, FVulkanQueue& InQueue);
~FVulkanDiagnosticBuffer();
// :todo: Bindings for shader asserts, etc
#if WITH_RHI_BREADCRUMBS
void WriteMarkerIn(FVulkanCommandBuffer& CommandBuffer, FRHIBreadcrumbNode* Breadcrumb) const;
void WriteMarkerOut(FVulkanCommandBuffer& CommandBuffer, FRHIBreadcrumbNode* Breadcrumb) const;
uint32 ReadMarkerIn()
{
Allocation.InvalidateMappedMemory(&Device);
return Data->MarkerIn;
}
uint32 ReadMarkerOut()
{
Allocation.InvalidateMappedMemory(&Device);
return Data->MarkerOut;
}
#endif // WITH_RHI_BREADCRUMBS
bool IsValid() const { return (Buffer != VK_NULL_HANDLE); }
private:
FVulkanDevice& Device;
FVulkanQueue& Queue;
VkBuffer Buffer = VK_NULL_HANDLE;
VulkanRHI::FVulkanAllocation Allocation;
#if WITH_RHI_BREADCRUMBS
// Extend lifetime of breadcrumbs so we can use the pointers directly
// One array per frame, and cycle which array is used on EndFrame
TArray<FRHIBreadcrumbAllocatorArray> ExtendedBreadcrumbAllocators;
int32 CurrentExtendedIndex = 0;
#endif // WITH_RHI_BREADCRUMBS
friend FVulkanDynamicRHI;
};