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

148 lines
5.6 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "MetalRHIPrivate.h"
#include "ShaderPipelineCache.h"
#include "MetalShaderResources.h"
/**
* The sampler, buffer and texture resource limits as defined here:
* https://developer.apple.com/library/ios/documentation/Miscellaneous/Conceptual/MetalProgrammingGuide/Render-Ctx/Render-Ctx.html
*/
#if PLATFORM_IOS
#define METAL_MAX_TEXTURES 31
typedef uint32 FMetalTextureMask;
#elif PLATFORM_MAC
#define METAL_MAX_TEXTURES 128
typedef __uint128_t FMetalTextureMask;
#else
#error "Unsupported Platform!"
#endif
typedef uint32 FMetalBufferMask;
typedef uint16 FMetalSamplerMask;
/** A structure for quick mask-testing of shader-stage resource bindings */
struct FMetalShaderResourceMask
{
FMetalTextureMask TextureMask;
FMetalBufferMask BufferMask;
FMetalSamplerMask SamplerMask;
};
enum EMetalShaderFrequency
{
EMetalShaderVertex = 0,
EMetalShaderFragment = 1,
EMetalShaderCompute = 2,
EMetalShaderStream = 3,
EMetalShaderRenderNum = 2,
EMetalShaderStagesNum = 4
};
enum EMetalLimits
{
ML_MaxSamplers = 16, /** Maximum number of samplers */
ML_MaxBuffers = METAL_MAX_BUFFERS, /** Maximum number of buffers */
ML_MaxTextures = METAL_MAX_TEXTURES, /** Maximum number of textures - there are more textures available on Mac than iOS */
ML_MaxViewports = 16 /** Technically this may be different at runtime, but this is the likely absolute upper-bound */
};
enum EMetalPipelineHashBits
{
NumBits_RenderTargetFormat = 6, //(x8=48),
NumBits_DepthFormat = 3, //(x1=3),
NumBits_StencilFormat = 3, //(x1=3),
NumBits_SampleCount = 3, //(x1=3),
NumBits_BlendState = 7, //(x8=56),
NumBits_PrimitiveTopology = 2, //(x1=2)
NumBits_AlphaToCoverage = 1, //(x1=1)
};
enum EMetalPipelineHashOffsets
{
Offset_BlendState0 = 0,
Offset_BlendState1 = Offset_BlendState0 + NumBits_BlendState,
Offset_BlendState2 = Offset_BlendState1 + NumBits_BlendState,
Offset_BlendState3 = Offset_BlendState2 + NumBits_BlendState,
Offset_BlendState4 = Offset_BlendState3 + NumBits_BlendState,
Offset_BlendState5 = Offset_BlendState4 + NumBits_BlendState,
Offset_BlendState6 = Offset_BlendState5 + NumBits_BlendState,
Offset_BlendState7 = Offset_BlendState6 + NumBits_BlendState,
Offset_PrimitiveTopology = Offset_BlendState7 + NumBits_BlendState,
Offset_RasterEnd = Offset_PrimitiveTopology + NumBits_PrimitiveTopology,
Offset_RenderTargetFormat0 = 64,
Offset_RenderTargetFormat1 = Offset_RenderTargetFormat0 + NumBits_RenderTargetFormat,
Offset_RenderTargetFormat2 = Offset_RenderTargetFormat1 + NumBits_RenderTargetFormat,
Offset_RenderTargetFormat3 = Offset_RenderTargetFormat2 + NumBits_RenderTargetFormat,
Offset_RenderTargetFormat4 = Offset_RenderTargetFormat3 + NumBits_RenderTargetFormat,
Offset_RenderTargetFormat5 = Offset_RenderTargetFormat4 + NumBits_RenderTargetFormat,
Offset_RenderTargetFormat6 = Offset_RenderTargetFormat5 + NumBits_RenderTargetFormat,
Offset_RenderTargetFormat7 = Offset_RenderTargetFormat6 + NumBits_RenderTargetFormat,
Offset_DepthFormat = Offset_RenderTargetFormat7 + NumBits_RenderTargetFormat,
Offset_StencilFormat = Offset_DepthFormat + NumBits_DepthFormat,
Offset_SampleCount = Offset_StencilFormat + NumBits_StencilFormat,
Offset_AlphaToCoverage = Offset_SampleCount + NumBits_SampleCount,
Offset_End = Offset_AlphaToCoverage + NumBits_AlphaToCoverage
};
class FMetalDevice;
class FMetalPipelineStateCacheManager
{
public:
FMetalPipelineStateCacheManager(FMetalDevice& Device);
~FMetalPipelineStateCacheManager();
private:
FDelegateHandle OnShaderPipelineCachePreOpenDelegate;
FDelegateHandle OnShaderPipelineCacheOpenedDelegate;
FDelegateHandle OnShaderPipelineCachePrecompilationCompleteDelegate;
/** Delegate handlers to track the ShaderPipelineCache precompile. */
void OnShaderPipelineCachePreOpen(FString const& Name, EShaderPlatform Platform, bool& bReady);
void OnShaderPipelineCacheOpened(FString const& Name, EShaderPlatform Platform, uint32 Count, const FGuid& VersionGuid, FShaderPipelineCache::FShaderCachePrecompileContext& ShaderCachePrecompileContext);
void OnShaderPipelineCachePrecompilationComplete(uint32 Count, double Seconds, const FShaderPipelineCache::FShaderCachePrecompileContext& ShaderCachePrecompileContext);
};
class FMetalShaderPipeline
{
public:
FMetalShaderPipeline(FMetalDevice& MetalDevice)
: Device(MetalDevice) {};
~FMetalShaderPipeline();
void Init();
void InitResourceMask();
void InitResourceMask(EMetalShaderFrequency Frequency);
FMetalDevice& Device;
MTLRenderPipelineStatePtr RenderPipelineState;
MTLComputePipelineStatePtr ComputePipelineState;
MTLRenderPipelineStatePtr StreamPipelineState;
TArray<uint32> BufferDataSizes[EMetalShaderStagesNum];
TMap<uint8, uint8> TextureTypes[EMetalShaderStagesNum];
FMetalShaderResourceMask ResourceMask[EMetalShaderStagesNum];
MTLRenderPipelineReflectionPtr RenderPipelineReflection;
MTLRenderPipelineReflectionPtr StreamPipelineReflection;
MTLComputePipelineReflectionPtr ComputePipelineReflection;
#if METAL_DEBUG_OPTIONS
NS::String* VertexSource = nullptr;
NS::String* FragmentSource = nullptr;
NS::String* ComputeSource = nullptr;
#if PLATFORM_SUPPORTS_MESH_SHADERS
NS::String* MeshSource = nullptr;
NS::String* ObjectSource = nullptr;
#endif
MTLRenderPipelineDescriptorPtr RenderDesc;
MTLMeshRenderPipelineDescriptorPtr MeshRenderDesc;
MTLRenderPipelineDescriptorPtr StreamDesc;
MTLComputePipelineDescriptorPtr ComputeDesc;
#endif
};
void ShutdownPipelineCache();
typedef TSharedPtr<FMetalShaderPipeline, ESPMode::ThreadSafe> FMetalShaderPipelinePtr;