// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. #pragma once #include "Engine/Core/Types/BaseTypes.h" #include "Shaders/GPUShaderProgram.h" #include "Enums.h" #include "GPUResource.h" /// /// Describes full graphics pipeline state within single object. /// API_CLASS(Sealed) class FLAXENGINE_API GPUPipelineState : public GPUResource { DECLARE_SCRIPTING_TYPE_NO_SPAWN(GPUPipelineState); static GPUPipelineState* Spawn(const SpawnParams& params); static GPUPipelineState* New(); public: /// /// Pipeline state description /// API_STRUCT() struct Description { DECLARE_SCRIPTING_TYPE_NO_SPAWN(Description); /// /// Enable/disable depth write /// API_FIELD() bool DepthWriteEnable; /// /// Enable/disable depth test /// API_FIELD() bool DepthTestEnable; /// /// Enable/disable depth clipping /// API_FIELD() bool DepthClipEnable; /// /// A function that compares depth data against existing depth data /// API_FIELD() ComparisonFunc DepthFunc; /// /// Vertex shader program /// API_FIELD() GPUShaderProgramVS* VS; /// /// Hull shader program /// API_FIELD() GPUShaderProgramHS* HS; /// /// Domain shader program /// API_FIELD() GPUShaderProgramDS* DS; /// /// Geometry shader program /// API_FIELD() GPUShaderProgramGS* GS; /// /// Pixel shader program /// API_FIELD() GPUShaderProgramPS* PS; /// /// Input primitives topology /// API_FIELD() PrimitiveTopologyType PrimitiveTopologyType; /// /// True if use wireframe rendering, otherwise false /// API_FIELD() bool Wireframe; /// /// Primitives culling mode /// API_FIELD() CullMode CullMode; /// /// Colors blending mode /// API_FIELD() BlendingMode BlendMode; public: /// /// Default description /// API_FIELD(ReadOnly) static Description Default; /// /// Default description without using depth buffer at all /// API_FIELD(ReadOnly) static Description DefaultNoDepth; /// /// Default description for fullscreen triangle rendering /// API_FIELD(ReadOnly) static Description DefaultFullscreenTriangle; }; protected: ShaderBindings _meta; public: #if BUILD_DEBUG /// /// The description of the pipeline state cached on creation in debug builds. Can be used to help with rendering crashes or issues and validation. /// Description DebugDesc; #endif public: /// /// Gets constant buffers usage mask (each set bit marks usage of the constant buffer at the bit index slot). Combined from all the used shader stages. /// /// The constant buffers usage mask. FORCE_INLINE uint32 GetUsedCBsMask() const { return _meta.UsedCBsMask; } /// /// Gets shader resources usage mask (each set bit marks usage of the shader resource slot at the bit index slot). Combined from all the used shader stages. /// /// The shader resource usage mask. FORCE_INLINE uint32 GetUsedSRsMask() const { return _meta.UsedSRsMask; } /// /// Gets unordered access usage mask (each set bit marks usage of the unordered access slot at the bit index slot). Combined from all the used shader stages. /// /// The unordered access usage mask. FORCE_INLINE uint32 GetUsedUAsMask() const { return _meta.UsedUAsMask; } public: /// /// Returns true if pipeline state is valid and ready to use /// /// True if is valid API_PROPERTY() virtual bool IsValid() const = 0; /// /// Create new state data /// /// Full pipeline state description /// True if cannot create state, otherwise false API_FUNCTION() virtual bool Init(API_PARAM(Ref) const Description& desc) { // Cache description in debug builds #if BUILD_DEBUG DebugDesc = desc; #endif // Cache shader stages usage flags for pipeline state _meta.InstructionsCount = 0; _meta.UsedCBsMask = 0; _meta.UsedSRsMask = 0; _meta.UsedUAsMask = 0; #define CHECK_STAGE(stage) \ if(desc.stage) { \ _meta.UsedCBsMask |= desc.stage->GetBindings().UsedCBsMask; \ _meta.UsedSRsMask |= desc.stage->GetBindings().UsedSRsMask; \ _meta.UsedUAsMask |= desc.stage->GetBindings().UsedUAsMask; \ } CHECK_STAGE(VS); CHECK_STAGE(HS); CHECK_STAGE(DS); CHECK_STAGE(GS); CHECK_STAGE(PS); #undef CHECK_STAGE return false; } public: // [GPUResource] ResourceType GetResourceType() const final override { return ResourceType::PipelineState; } };