Add **stencil buffer** support to GPUPipelineState

This commit is contained in:
Wojtek Figat
2023-06-19 13:46:37 +02:00
parent a6353c0bb9
commit f952a392de
5 changed files with 188 additions and 134 deletions

View File

@@ -90,96 +90,79 @@ GPUResourceType GPUPipelineState::GetResourceType() const
return GPUResourceType::PipelineState;
}
// @formatter:off
GPUPipelineState::Description GPUPipelineState::Description::Default =
{
// Enable/disable depth write
true,
// Enable/disable depth test
true,
// DepthClipEnable
true,
// DepthFunc
ComparisonFunc::Less,
// Vertex shader
nullptr,
// Hull shader
nullptr,
// Domain shader
nullptr,
// Geometry shader
nullptr,
// Pixel shader
nullptr,
// Primitives topology
PrimitiveTopologyType::Triangle,
// True if use wireframe rendering
false,
// Primitives culling mode
CullMode::Normal,
// Colors blending mode
BlendingMode::Opaque,
true, // DepthEnable
true, // DepthWriteEnable
true, // DepthClipEnable
ComparisonFunc::Less, // DepthFunc
false, // StencilEnable
0xff, // StencilReadMask
0xff, // StencilWriteMask
ComparisonFunc::Always, // StencilFunc
StencilOperation::Keep, // StencilFailOp
StencilOperation::Keep, // StencilDepthFailOp
StencilOperation::Keep, // StencilPassOp
nullptr, // VS
nullptr, // HS
nullptr, // DS
nullptr, // GS
nullptr, // PS
PrimitiveTopologyType::Triangle, // PrimitiveTopology
false, // Wireframe
CullMode::Normal, // CullMode
BlendingMode::Opaque, // BlendMode
};
GPUPipelineState::Description GPUPipelineState::Description::DefaultNoDepth =
{
// Enable/disable depth write
false,
// Enable/disable depth test
false,
// DepthClipEnable
false,
// DepthFunc
ComparisonFunc::Less,
// Vertex shader
nullptr,
// Hull shader
nullptr,
// Domain shader
nullptr,
// Geometry shader
nullptr,
// Pixel shader
nullptr,
// Primitives topology
PrimitiveTopologyType::Triangle,
// True if use wireframe rendering
false,
// Primitives culling mode
CullMode::Normal,
// Colors blending mode
BlendingMode::Opaque,
false, // DepthEnable
false, // DepthWriteEnable
false, // DepthClipEnable
ComparisonFunc::Less, // DepthFunc
false, // StencilEnable
0xff, // StencilReadMask
0xff, // StencilWriteMask
ComparisonFunc::Always, // StencilFunc
StencilOperation::Keep, // StencilFailOp
StencilOperation::Keep, // StencilDepthFailOp
StencilOperation::Keep, // StencilPassOp
nullptr, // VS
nullptr, // HS
nullptr, // DS
nullptr, // GS
nullptr, // PS
PrimitiveTopologyType::Triangle, // PrimitiveTopology
false, // Wireframe
CullMode::Normal, // CullMode
BlendingMode::Opaque, // BlendMode
};
GPUPipelineState::Description GPUPipelineState::Description::DefaultFullscreenTriangle =
{
// Enable/disable depth write
false,
// Enable/disable depth test
false,
// DepthClipEnable
false,
// DepthFunc
ComparisonFunc::Less,
// Vertex shader
nullptr,
// Set to default quad VS via GPUDevice
// Hull shader
nullptr,
// Domain shader
nullptr,
// Geometry shader
nullptr,
// Pixel shader
nullptr,
// Primitives topology
PrimitiveTopologyType::Triangle,
// True if use wireframe rendering
false,
// Primitives culling mode
CullMode::TwoSided,
// Colors blending mode
BlendingMode::Opaque,
false, // DepthEnable
false, // DepthWriteEnable
false, // DepthClipEnable
ComparisonFunc::Less, // DepthFunc
false, // StencilEnable
0xff, // StencilReadMask
0xff, // StencilWriteMask
ComparisonFunc::Always, // StencilFunc
StencilOperation::Keep, // StencilFailOp
StencilOperation::Keep, // StencilDepthFailOp
StencilOperation::Keep, // StencilPassOp
nullptr, // VS (Set to default quad VS via GPUDevice)
nullptr, // HS
nullptr, // DS
nullptr, // GS
nullptr, // PS
PrimitiveTopologyType::Triangle, // PrimitiveTopology
false, // Wireframe
CullMode::TwoSided, // CullMode
BlendingMode::Opaque, // BlendMode
};
// @formatter:on
GPUResource::GPUResource()
: ScriptingObject(SpawnParams(Guid::New(), TypeInitializer))

View File

@@ -7,6 +7,31 @@
#include "Enums.h"
#include "GPUResource.h"
/// <summary>
/// Stencil operation modes.
/// </summary>
API_ENUM() enum class StencilOperation : byte
{
// Keep the existing stencil data.
Keep,
// Set the stencil data to 0.
Zero,
// Set the stencil data to the reference value (set via GPUContext::SetStencilRef).
Replace,
// Increment the stencil value by 1, and clamp the result.
IncrementSaturated,
// Decrement the stencil value by 1, and clamp the result.
DecrementSaturated,
// Invert the stencil data.
Invert,
// Increment the stencil value by 1, and wrap the result if necessary.
Increment,
// Decrement the stencil value by 1, and wrap the result if necessary.
Decrement,
API_ENUM(Attributes="HideInEditor") MAX
};
/// <summary>
/// Describes full graphics pipeline state within single object.
/// </summary>
@@ -44,6 +69,41 @@ public:
/// </summary>
API_FIELD() ComparisonFunc DepthFunc;
/// <summary>
/// Enable/disable stencil buffer usage
/// </summary>
API_FIELD() bool StencilEnable;
/// <summary>
/// The read mask applied to the reference value and each stencil buffer entry to determine the significant bits for the stencil test.
/// </summary>
API_FIELD() uint8 StencilReadMask;
/// <summary>
/// The write mask applied to values written into the stencil buffer.
/// </summary>
API_FIELD() uint8 StencilWriteMask;
/// <summary>
/// The comparison function for the stencil test.
/// </summary>
API_FIELD() ComparisonFunc StencilFunc;
/// <summary>
/// The stencil operation to perform when stencil testing fails.
/// </summary>
API_FIELD() StencilOperation StencilFailOp;
/// <summary>
/// The stencil operation to perform when stencil testing passes and depth testing fails.
/// </summary>
API_FIELD() StencilOperation StencilDepthFailOp;
/// <summary>
/// The stencil operation to perform when stencil testing and depth testing both pass.
/// </summary>
API_FIELD() StencilOperation StencilPassOp;
/// <summary>
/// Vertex shader program
/// </summary>

View File

@@ -9,6 +9,31 @@
#include "Engine/GraphicsDevice/DirectX/RenderToolsDX.h"
#include "Engine/Graphics/PixelFormatExtensions.h"
static D3D12_STENCIL_OP ToStencilOp(StencilOperation value)
{
switch (value)
{
case StencilOperation::Keep:
return D3D12_STENCIL_OP_KEEP;
case StencilOperation::Zero:
return D3D12_STENCIL_OP_ZERO;
case StencilOperation::Replace:
return D3D12_STENCIL_OP_REPLACE;
case StencilOperation::IncrementSaturated:
return D3D12_STENCIL_OP_INCR_SAT;
case StencilOperation::DecrementSaturated:
return D3D12_STENCIL_OP_DECR_SAT;
case StencilOperation::Invert:
return D3D12_STENCIL_OP_INVERT;
case StencilOperation::Increment:
return D3D12_STENCIL_OP_INCR;
case StencilOperation::Decrement:
return D3D12_STENCIL_OP_DECR;
default:
return D3D12_STENCIL_OP_KEEP;
};
}
GPUPipelineStateDX12::GPUPipelineStateDX12(GPUDeviceDX12* device)
: GPUResourceDX12(device, StringView::Empty)
, _states(16)
@@ -169,12 +194,14 @@ bool GPUPipelineStateDX12::Init(const Description& desc)
psDesc.DepthStencilState.DepthEnable = !!desc.DepthEnable;
psDesc.DepthStencilState.DepthWriteMask = desc.DepthWriteEnable ? D3D12_DEPTH_WRITE_MASK_ALL : D3D12_DEPTH_WRITE_MASK_ZERO;
psDesc.DepthStencilState.DepthFunc = static_cast<D3D12_COMPARISON_FUNC>(desc.DepthFunc);
psDesc.DepthStencilState.StencilEnable = FALSE;
psDesc.DepthStencilState.StencilReadMask = D3D12_DEFAULT_STENCIL_READ_MASK;
psDesc.DepthStencilState.StencilWriteMask = D3D12_DEFAULT_STENCIL_WRITE_MASK;
const D3D12_DEPTH_STENCILOP_DESC defaultStencilOp = { D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_COMPARISON_FUNC_ALWAYS };
psDesc.DepthStencilState.FrontFace = defaultStencilOp;
psDesc.DepthStencilState.BackFace = defaultStencilOp;
psDesc.DepthStencilState.StencilEnable = !!desc.StencilEnable;
psDesc.DepthStencilState.StencilReadMask = desc.StencilReadMask;
psDesc.DepthStencilState.StencilWriteMask = desc.StencilWriteMask;
psDesc.DepthStencilState.FrontFace.StencilFailOp = ToStencilOp(desc.StencilFailOp);
psDesc.DepthStencilState.FrontFace.StencilDepthFailOp = ToStencilOp(desc.StencilDepthFailOp);
psDesc.DepthStencilState.FrontFace.StencilPassOp = ToStencilOp(desc.StencilPassOp);
psDesc.DepthStencilState.FrontFace.StencilFunc = static_cast<D3D12_COMPARISON_FUNC>(desc.StencilFunc);
psDesc.DepthStencilState.BackFace = psDesc.DepthStencilState.FrontFace;
// Rasterizer State
psDesc.RasterizerState.FillMode = desc.Wireframe ? D3D12_FILL_MODE_WIREFRAME : D3D12_FILL_MODE_SOLID;

View File

@@ -26,71 +26,22 @@ namespace DescriptorSet
{
// Vertex shader stage
Vertex = 0,
// Pixel shader stage
Pixel = 1,
// Geometry shader stage
Geometry = 2,
// Hull shader stage
Hull = 3,
// Domain shader stage
Domain = 4,
// Graphics pipeline stages count
GraphicsStagesCount = 5,
// Compute pipeline slot
Compute = 0,
// The maximum amount of slots for all stages
Max = 5,
};
inline Stage GetSetForFrequency(ShaderStage stage)
{
switch (stage)
{
case ShaderStage::Vertex:
return Vertex;
case ShaderStage::Hull:
return Hull;
case ShaderStage::Domain:
return Domain;
case ShaderStage::Pixel:
return Pixel;
case ShaderStage::Geometry:
return Geometry;
case ShaderStage::Compute:
return Compute;
default:
CRASH;
return Max;
}
}
inline ShaderStage GetFrequencyForGfxSet(Stage stage)
{
switch (stage)
{
case Vertex:
return ShaderStage::Vertex;
case Hull:
return ShaderStage::Hull;
case Domain:
return ShaderStage::Domain;
case Pixel:
return ShaderStage::Pixel;
case Geometry:
return ShaderStage::Geometry;
default:
CRASH;
return (ShaderStage)ShaderStage_Count;
}
}
template<typename T>
inline bool CopyAndReturnNotEqual(T& a, T b)
{

View File

@@ -9,6 +9,31 @@
#include "Engine/Core/Log.h"
#include "Engine/Profiler/ProfilerCPU.h"
static VkStencilOp ToVulkanStencilOp(const StencilOperation value)
{
switch (value)
{
case StencilOperation::Keep:
return VK_STENCIL_OP_KEEP;
case StencilOperation::Zero:
return VK_STENCIL_OP_ZERO;
case StencilOperation::Replace:
return VK_STENCIL_OP_REPLACE;
case StencilOperation::IncrementSaturated:
return VK_STENCIL_OP_INCREMENT_AND_CLAMP;
case StencilOperation::DecrementSaturated:
return VK_STENCIL_OP_DECREMENT_AND_CLAMP;
case StencilOperation::Invert:
return VK_STENCIL_OP_INVERT;
case StencilOperation::Increment:
return VK_STENCIL_OP_INCREMENT_AND_WRAP;
case StencilOperation::Decrement:
return VK_STENCIL_OP_DECREMENT_AND_WRAP;
default:
return VK_STENCIL_OP_KEEP;
}
}
GPUShaderProgramCSVulkan::~GPUShaderProgramCSVulkan()
{
if (_pipelineState)
@@ -289,6 +314,14 @@ bool GPUPipelineStateVulkan::Init(const Description& desc)
_descDepthStencil.depthTestEnable = desc.DepthEnable;
_descDepthStencil.depthWriteEnable = desc.DepthWriteEnable;
_descDepthStencil.depthCompareOp = RenderToolsVulkan::ToVulkanCompareOp(desc.DepthFunc);
_descDepthStencil.stencilTestEnable = desc.StencilEnable;
_descDepthStencil.front.compareMask = desc.StencilReadMask;
_descDepthStencil.front.writeMask = desc.StencilWriteMask;
_descDepthStencil.front.compareOp = RenderToolsVulkan::ToVulkanCompareOp(desc.StencilFunc);
_descDepthStencil.front.failOp = ToVulkanStencilOp(desc.StencilFailOp);
_descDepthStencil.front.depthFailOp = ToVulkanStencilOp(desc.StencilDepthFailOp);
_descDepthStencil.front.passOp = ToVulkanStencilOp(desc.StencilPassOp);
_descDepthStencil.front = _descDepthStencil.back;
_desc.pDepthStencilState = &_descDepthStencil;
// Rasterization