// Copyright Epic Games, Inc. All Rights Reserved. // The ShaderPrint system uses a RWBuffer to capture any debug print from a shader. // This means that the buffer needs to be bound for the shader you wish to debug. // It would be ideal if that was automatic (maybe by having a fixed bind point for the buffer and binding it for the entire view). // But for now you need to manually add binding information to your FShader class. // To do this use SHADER_PARAMETER_STRUCT_INCLUDE(ShaderPrint::FShaderParameters) in your FShader::FParameters declaration. // Then call a variant of SetParameters(). #pragma once #include "CoreMinimal.h" #include "RenderGraphDefinitions.h" #include "RenderGraphResources.h" #include "ShaderParameterMacros.h" #include "ShaderParameters.h" class FRDGBuilder; class FSceneView; class FViewInfo; struct FFrozenShaderPrintData; struct FGlobalShaderPermutationParameters; struct FShaderCompilerEnvironment; struct FShaderPrintData; namespace ShaderPrint { // ShaderPrint uniform buffer layout BEGIN_GLOBAL_SHADER_PARAMETER_STRUCT(FShaderPrintCommonParameters, RENDERER_API) SHADER_PARAMETER(FIntPoint, Resolution) SHADER_PARAMETER(FIntPoint, CursorCoord) SHADER_PARAMETER(FVector3f, TranslatedWorldOffset) SHADER_PARAMETER(FVector2f, FontSize) SHADER_PARAMETER(FVector2f, FontSpacing) SHADER_PARAMETER(uint32, MaxCharacterCount) SHADER_PARAMETER(uint32, MaxSymbolCount) SHADER_PARAMETER(uint32, MaxStateCount) SHADER_PARAMETER(uint32, MaxLineCount) SHADER_PARAMETER(uint32, MaxTriangleCount) SHADER_PARAMETER(uint32, IsDrawLocked) END_GLOBAL_SHADER_PARAMETER_STRUCT() // ShaderPrint parameter struct declaration BEGIN_SHADER_PARAMETER_STRUCT(FShaderParameters, ) SHADER_PARAMETER_STRUCT_REF(FShaderPrintCommonParameters, Common) SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer, ShaderPrint_StateBuffer) SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer, ShaderPrint_RWEntryBuffer) END_SHADER_PARAMETER_STRUCT() // Does the platform support the ShaderPrint system? // Use this to create debug shader permutations only for supported platforms. RENDERER_API bool IsSupported(EShaderPlatform Platform); // Set any flags or defines needed when using ShaderPrint RENDERER_API void ModifyCompilationEnvironment(const EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment); RENDERER_API void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment); // Have we enabled the ShaderPrint system? // Note that even when the ShaderPrint system is enabled, it may be disabled on any view due to platform support or view flags. RENDERER_API bool IsEnabled(); // Force enable/disable the ShaderPrint system. RENDERER_API void SetEnabled(bool bInEnabled); // Returns true if the shader print data is valid for binding. // This should be checked before using with any ShaderPrint shader permutation. RENDERER_API bool IsValid(FShaderPrintData const& InShaderPrintData); // Returns true if the shader print data is enabled. // When the shader print data is valid but disabled then it can be used with any ShaderPrint shader permutation, but no data will be captured. // This can be checked to early out on any work that is only generating ShaderPrint data. RENDERER_API bool IsEnabled(FShaderPrintData const& InShaderPrintData); // Returns true if the default view exists and has valid shader print data. // This should be checked before using with any ShaderPrint shader permutation. RENDERER_API bool IsDefaultViewValid(); // Returns true if the default view exists and shader print data that is enabled. // When the shader print data is valid but disabled then it can be used with any ShaderPrint shader permutation, but no data will be captured. // This can be checked to early out on any work that is only generating ShaderPrint data. RENDERER_API bool IsDefaultViewEnabled(); /** * Call to ensure enough space for some number of characters, is added cumulatively each frame, to make * it possible for several systems to request a certain number independently. * Is used to grow the max element count for subsequent frames (as the allocation happens early in the frame). * @param The number of characters requested. */ RENDERER_API void RequestSpaceForCharacters(uint32 MaxElementCount); /** * Call to ensure enough space for some number of lines segments, is added cumulatively each frame, to make * it possible for several systems to request a certain number independently. * Is used to grow the max element count for subsequent frames (as the allocation happens early in the frame). * @param The number of line segments requested. */ RENDERER_API void RequestSpaceForLines(uint32 MaxElementCount); /** * Call to ensure enough space for some number of solid triangles, is added cumulatively each frame, to make * it possible for several systems to request a certain number independently. * Is used to grow the max element count for subsequent frames (as the allocation happens early in the frame). * @param The number of triangles requested. */ RENDERER_API void RequestSpaceForTriangles(uint32 MaxElementCount); /** Structure containing setup for shader print capturing. */ struct FShaderPrintSetup { /** Construct with shader print disabled setup. */ FShaderPrintSetup() = default; /** Construct with view and system defaults. */ RENDERER_API FShaderPrintSetup(FSceneView const& InView); /** Construct with view rectangle and system defaults. */ RENDERER_API FShaderPrintSetup(FIntRect InViewRect); /** The shader print system's enabled state. This is set in the constructor and should't be overriden. */ bool bEnabled = false; /** Expected viewport rectangle. */ FIntRect ViewRect = FIntRect(0, 0, 1, 1); /** Cursor pixel position within viewport. Can be used for isolating a pixel to debug. */ FIntPoint CursorCoord = FIntPoint(-1, -1); /** PreView translation used for storing line positions in translated world space. */ FVector PreViewTranslation = FVector::ZeroVector; /** DPI scale to take into account when drawing font. */ float DPIScale = 1.f; /** Font size in pixels. */ FIntPoint FontSize = 1; /** Font spacing in pixels (not including font size). */ FIntPoint FontSpacing = 1; /** Initial size of character buffer. Will also be increased by RequestSpaceForCharacters(). */ uint32 MaxCharacterCount = 0; /** Initial size of widget buffer. */ uint32 MaxStateCount = 0; /** Initial size of line buffer. Will also be increased by RequestSpaceForLines(). */ uint32 MaxLineCount = 0; /** Initial size of triangle buffer. Will also be increased by RequestSpaceForLines(). */ uint32 MaxTriangleCount = 0; // Whether current draw is locked or not. Useful to stop rendering new stuff on top of the history. */ bool bIsDrawLocked = false; }; /** Fill the ShaderPrintCommonParameters uniform buffer structure for our setup. */ RENDERER_API void GetParameters(FShaderPrintSetup const& InSetup, FShaderPrintCommonParameters& OutParameters); /** Create the shader print render data. This allocates and clears the render buffers. */ RENDERER_API FShaderPrintData CreateShaderPrintData(FRDGBuilder& GraphBuilder, FShaderPrintSetup const& InSetup); /** Make the buffers in a FShaderPrintData object external to an RDG builder. Do this for later reuse, or when submiting for later rendering. */ RENDERER_API FFrozenShaderPrintData FreezeShaderPrintData(FRDGBuilder& GraphBuilder, FShaderPrintData& ShaderPrintData); /** Import the shader print buffers into an RDG builder and recreate the FShaderPrintData object. */ RENDERER_API FShaderPrintData UnFreezeShaderPrintData(FRDGBuilder& GraphBuilder, FFrozenShaderPrintData& FrozenShaderPrintData); /** Submit shader print data for display in the next rendered frame. The data is displayed in views from the scene, or all views if InScene==nullptr. */ RENDERER_API void SubmitShaderPrintData(FFrozenShaderPrintData& InData, FSceneInterface const* InScene); UE_DEPRECATED(5.2, "Use the version of this function that takes a FSceneInterface") RENDERER_API void SubmitShaderPrintData(FFrozenShaderPrintData& InData); /** Fill the FShaderParameters with an explicit FShaderPrintData managed by the calling code. */ RENDERER_API void SetParameters(FRDGBuilder& GraphBuilder, FShaderPrintData const& InData, FShaderParameters& OutParameters); /** Fill the FShaderParameters with the opaque FShaderPrintData from the current default view. */ RENDERER_API void SetParameters(FRDGBuilder& GraphBuilder, FShaderParameters& OutParameters); UE_DEPRECATED(5.1, "Use one of the other implementations of SetParameters()") void SetParameters(FRDGBuilder& GraphBuilder, const FViewInfo& View, FShaderParameters& OutParameters); // Experimental GPU string // // In Cpp: // SHADER_PARAMETER_STRUCT(ShaderPrint::FStrings::FShaderPararameters, MyVariable) // ShaderPrint::FStrings MyVariable; // MyVariable.Add(FString(...), StringId); // // In shader: // FSTRINGS(MyVariable) // void foo() // { // InitShaderPrintContext Ctx = InitShaderPrintContext(...); // PrintMyVariable(Ctx, StringId, FontWhite); // } struct FStrings { public: BEGIN_SHADER_PARAMETER_STRUCT(FShaderParameters, ) SHADER_PARAMETER(uint32, InfoCount) SHADER_PARAMETER(uint32, CharCount) SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer, InfoBuffer) SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer, CharBuffer) END_SHADER_PARAMETER_STRUCT() RENDERER_API FStrings(uint32 InAvgEntryCount=128u, uint32 InAvgStringLength=32u); RENDERER_API void Add(const FString& In, uint32 EntryID); RENDERER_API void Add(const FString& In); RENDERER_API FShaderParameters GetParameters(FRDGBuilder& GraphBuilder); private: struct FEntryInfo { uint32 EntryID; uint16 Offset; uint8 Length; uint8 Pad0; }; TArray Infos; TArray Chars; }; } /** * Structure containing shader print render data. * This is automatically created, setup and rendered for each view. * Also it is possible for client code to create and own this. * If this is client managed then the client can queue for rendering by calling: * (i) FreezeShaderPrintData() to "freeze" the data which exports it from the current RDG builder context. * (ii) SubmitShaderPrintData() to submit the frozen data for later thawing and rendering. */ struct FShaderPrintData { ShaderPrint::FShaderPrintSetup Setup; TUniformBufferRef UniformBuffer; FRDGBufferRef ShaderPrintEntryBuffer = nullptr; FRDGBufferRef ShaderPrintStateBuffer = nullptr; }; /** * Structure containing "frozen" shader print render data. * This is in a state so that it: * (i) Can be thawed by the client for continued gathering of shader print glyphs, or * (ii) Can be submitted for later rendering using SubmitShaderPrintData(). */ struct FFrozenShaderPrintData { ShaderPrint::FShaderPrintSetup Setup; TRefCountPtr ShaderPrintEntryBuffer; TRefCountPtr ShaderPrintStateBuffer; };