Files
UnrealEngine/Engine/Source/Runtime/VulkanRHI/Private/VulkanPendingState.h
2025-05-18 13:04:45 +08:00

346 lines
9.5 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved..
/*=============================================================================
VulkanPendingState.h: Private VulkanPendingState definitions.
=============================================================================*/
#pragma once
// Dependencies
#include "VulkanConfiguration.h"
#include "VulkanState.h"
#include "VulkanResources.h"
#include "VulkanUtil.h"
#include "VulkanViewport.h"
#include "VulkanDynamicRHI.h"
#include "VulkanPipeline.h"
#include "VulkanPipelineState.h"
// All the current compute pipeline states in use
class FVulkanPendingComputeState
{
public:
FVulkanPendingComputeState(FVulkanDevice& InDevice)
: Device(InDevice)
{
}
~FVulkanPendingComputeState();
void Reset()
{
CurrentPipeline = nullptr;
CurrentState = nullptr;
}
void SetComputePipeline(FVulkanComputePipeline* InComputePipeline)
{
if (InComputePipeline != CurrentPipeline)
{
CurrentPipeline = InComputePipeline;
FVulkanComputePipelineDescriptorState** Found = PipelineStates.Find(InComputePipeline);
if (Found)
{
CurrentState = *Found;
check(CurrentState->ComputePipeline == InComputePipeline);
}
else
{
CurrentState = new FVulkanComputePipelineDescriptorState(Device, InComputePipeline);
PipelineStates.Add(CurrentPipeline, CurrentState);
}
CurrentState->Reset();
}
}
void PrepareForDispatch(FVulkanCommandListContext& Context);
inline const FVulkanComputeShader* GetCurrentShader() const
{
return CurrentPipeline ? ResourceCast(CurrentPipeline->GetComputeShader()) : nullptr;
}
void SetUAVForUBResource(uint32 DescriptorSet, uint32 BindingIndex, FVulkanUnorderedAccessView* UAV);
inline void SetUAVForStage(uint32 UAVIndex, FVulkanUnorderedAccessView* UAV)
{
SetUAVForUBResource(ShaderStage::Compute, UAVIndex, UAV);
}
inline void SetTextureForStage(uint32 TextureIndex, const FVulkanTexture* Texture, VkImageLayout Layout)
{
CurrentState->SetTexture(ShaderStage::Compute, TextureIndex, Texture, Layout);
}
inline void SetSamplerStateForStage(uint32 SamplerIndex, FVulkanSamplerState* Sampler)
{
CurrentState->SetSamplerState(ShaderStage::Compute, SamplerIndex, Sampler);
}
inline void SetTextureForUBResource(int32 DescriptorSet, uint32 BindingIndex, const FVulkanTexture* Texture, VkImageLayout Layout)
{
CurrentState->SetTexture(DescriptorSet, BindingIndex, Texture, Layout);
}
void SetSRVForUBResource(uint32 DescriptorSet, uint32 BindingIndex, FVulkanShaderResourceView* SRV);
inline void SetSRVForStage(uint32 SRVIndex, FVulkanShaderResourceView* SRV)
{
SetSRVForUBResource(ShaderStage::Compute, SRVIndex, SRV);
}
inline void SetPackedGlobalShaderParameter(uint32 BufferIndex, uint32 Offset, uint32 NumBytes, const void* NewValue)
{
CurrentState->SetPackedGlobalShaderParameter(BufferIndex, Offset, NumBytes, NewValue);
}
inline void SetSamplerStateForUBResource(uint32 DescriptorSet, uint32 BindingIndex, FVulkanSamplerState* Sampler)
{
CurrentState->SetSamplerState(DescriptorSet, BindingIndex, Sampler);
}
void NotifyDeletedPipeline(FVulkanComputePipeline* Pipeline)
{
PipelineStates.Remove(Pipeline);
}
protected:
FVulkanComputePipeline* CurrentPipeline = nullptr;
FVulkanComputePipelineDescriptorState* CurrentState = nullptr;
TMap<FVulkanComputePipeline*, FVulkanComputePipelineDescriptorState*> PipelineStates;
FVulkanDevice& Device;
friend class FVulkanCommandListContext;
};
// All the current gfx pipeline states in use
class FVulkanPendingGfxState
{
public:
FVulkanPendingGfxState(FVulkanDevice& InDevice)
: Device(InDevice)
{
Reset();
}
~FVulkanPendingGfxState();
void Reset()
{
Viewports.SetNumZeroed(1);
Scissors.SetNumZeroed(1);
StencilRef = 0;
bScissorEnable = false;
CurrentPipeline = nullptr;
CurrentState = nullptr;
bDirtyVertexStreams = true;
PrimitiveType = PT_Num;
//#todo-rco: Would this cause issues?
//FMemory::Memzero(PendingStreams);
}
const uint64 GetCurrentShaderKey(EShaderFrequency Frequency) const
{
return (CurrentPipeline ? CurrentPipeline->GetShaderKey(Frequency) : 0);
}
const uint64 GetCurrentShaderKey(ShaderStage::EStage Stage) const
{
return GetCurrentShaderKey(ShaderStage::GetFrequencyForGfxStage(Stage));
}
const FVulkanShader* GetCurrentShader(EShaderFrequency Frequency) const
{
return (CurrentPipeline ? CurrentPipeline->GetVulkanShader(Frequency) : nullptr);
}
void SetViewport(float MinX, float MinY, float MinZ, float MaxX, float MaxY, float MaxZ)
{
Viewports.SetNumZeroed(1);
Viewports[0].x = MinX;
Viewports[0].y = MinY;
Viewports[0].width = MaxX - MinX;
Viewports[0].height = MaxY - MinY;
Viewports[0].minDepth = MinZ;
if (MinZ == MaxZ)
{
// Engine pases in some cases MaxZ as 0.0
Viewports[0].maxDepth = MinZ + 1.0f;
}
else
{
Viewports[0].maxDepth = MaxZ;
}
SetScissorRect((uint32)MinX, (uint32)MinY, (uint32)(MaxX - MinX), (uint32)(MaxY - MinY));
bScissorEnable = false;
}
void SetMultiViewport(const TArrayView<VkViewport>& InViewports)
{
Viewports = InViewports;
// Set the scissor rects appropriately.
Scissors.SetNumZeroed(Viewports.Num());
for (int32 Idx = 0; Idx < Scissors.Num(); ++Idx)
{
Scissors[Idx].offset.x = Viewports[Idx].x;
Scissors[Idx].offset.y = Viewports[Idx].y;
Scissors[Idx].extent.width = Viewports[Idx].width;
Scissors[Idx].extent.height = Viewports[Idx].height;
}
bScissorEnable = true;
}
inline void SetScissor(bool bInEnable, uint32 MinX, uint32 MinY, uint32 MaxX, uint32 MaxY)
{
if (bInEnable)
{
SetScissorRect(MinX, MinY, MaxX - MinX, MaxY - MinY);
}
else
{
checkf(Viewports.Num() > 0, TEXT("At least one Viewport is expected to be configured."));
SetScissorRect(Viewports[0].x, Viewports[0].y, Viewports[0].width, Viewports[0].height);
}
bScissorEnable = bInEnable;
}
inline void SetScissorRect(uint32 MinX, uint32 MinY, uint32 Width, uint32 Height)
{
Scissors.SetNumZeroed(1);
Scissors[0].offset.x = MinX;
Scissors[0].offset.y = MinY;
Scissors[0].extent.width = Width;
Scissors[0].extent.height = Height;
}
inline void SetStreamSource(uint32 StreamIndex, VkBuffer VertexBuffer, uint32 Offset)
{
PendingStreams[StreamIndex].Stream = VertexBuffer;
PendingStreams[StreamIndex].BufferOffset = Offset;
bDirtyVertexStreams = true;
}
inline void Bind(VkCommandBuffer CmdBuffer)
{
CurrentPipeline->Bind(CmdBuffer);
}
inline void SetTextureForStage(ShaderStage::EStage Stage, uint32 ParameterIndex, const FVulkanTexture* Texture, VkImageLayout Layout)
{
CurrentState->SetTexture(Stage, ParameterIndex, Texture, Layout);
}
inline void SetTextureForUBResource(uint8 DescriptorSet, uint32 BindingIndex, const FVulkanTexture* Texture, VkImageLayout Layout)
{
CurrentState->SetTexture(DescriptorSet, BindingIndex, Texture, Layout);
}
template<bool bDynamic>
inline void SetUniformBuffer(uint8 DescriptorSet, uint32 BindingIndex, const FVulkanUniformBuffer* UniformBuffer)
{
CurrentState->SetUniformBuffer<bDynamic>(DescriptorSet, BindingIndex, UniformBuffer);
}
void SetUAVForUBResource(uint8 DescriptorSet, uint32 BindingIndex, FVulkanUnorderedAccessView* UAV);
inline void SetUAVForStage(ShaderStage::EStage Stage, uint32 ParameterIndex, FVulkanUnorderedAccessView* UAV)
{
SetUAVForUBResource(Stage, ParameterIndex, UAV);
}
void SetSRVForUBResource(uint8 DescriptorSet, uint32 BindingIndex, FVulkanShaderResourceView* SRV);
inline void SetSRVForStage(ShaderStage::EStage Stage, uint32 ParameterIndex, FVulkanShaderResourceView* SRV)
{
SetSRVForUBResource(Stage, ParameterIndex, SRV);
}
inline void SetSamplerStateForStage(ShaderStage::EStage Stage, uint32 ParameterIndex, FVulkanSamplerState* Sampler)
{
CurrentState->SetSamplerState(Stage, ParameterIndex, Sampler);
}
inline void SetSamplerStateForUBResource(uint32 DescriptorSet, uint32 BindingIndex, FVulkanSamplerState* Sampler)
{
CurrentState->SetSamplerState(DescriptorSet, BindingIndex, Sampler);
}
inline void SetPackedGlobalShaderParameter(ShaderStage::EStage Stage, uint32 BufferIndex, uint32 Offset, uint32 NumBytes, const void* NewValue)
{
CurrentState->SetPackedGlobalShaderParameter(Stage, BufferIndex, Offset, NumBytes, NewValue);
}
void PrepareForDraw(FVulkanCommandListContext& Context);
bool SetGfxPipeline(FVulkanRHIGraphicsPipelineState* InGfxPipeline, bool bForceReset);
inline void UpdateDynamicStates(FVulkanCommandBuffer& CommandBuffer)
{
InternalUpdateDynamicStates(CommandBuffer);
}
inline void SetStencilRef(uint32 InStencilRef)
{
if (InStencilRef != StencilRef)
{
StencilRef = InStencilRef;
}
}
void NotifyDeletedPipeline(FVulkanRHIGraphicsPipelineState* Pipeline)
{
PipelineStates.Remove(Pipeline);
}
inline void MarkNeedsDynamicStates()
{
}
protected:
TArray<VkViewport, TInlineAllocator<2>> Viewports;
TArray<VkRect2D, TInlineAllocator<2>> Scissors;
EPrimitiveType PrimitiveType = PT_Num;
uint32 StencilRef;
bool bScissorEnable;
bool bNeedToClear;
FVulkanRHIGraphicsPipelineState* CurrentPipeline;
FVulkanGraphicsPipelineDescriptorState* CurrentState;
TMap<FVulkanRHIGraphicsPipelineState*, FVulkanGraphicsPipelineDescriptorState*> PipelineStates;
struct FVertexStream
{
FVertexStream() :
Stream(VK_NULL_HANDLE),
BufferOffset(0)
{
}
VkBuffer Stream;
uint32 BufferOffset;
};
FVertexStream PendingStreams[MaxVertexElementCount];
bool bDirtyVertexStreams;
void InternalUpdateDynamicStates(FVulkanCommandBuffer& CommandBuffer);
void UpdateInputAttachments(FVulkanFramebuffer* Framebuffer);
FVulkanDevice& Device;
friend class FVulkanCommandListContext;
};