Add Quad Overdraw debug view mode
This commit is contained in:
@@ -374,4 +374,18 @@ void PS_Depth(PixelInput input)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if _PS_QuadOverdraw
|
||||||
|
|
||||||
|
#include "./Flax/Editor/QuadOverdraw.hlsl"
|
||||||
|
|
||||||
|
// Pixel Shader function for Quad Overdraw Pass (editor-only)
|
||||||
|
[earlydepthstencil]
|
||||||
|
META_PS(USE_EDITOR, FEATURE_LEVEL_SM5)
|
||||||
|
void PS_QuadOverdraw(float4 svPos : SV_Position, uint primId : SV_PrimitiveID)
|
||||||
|
{
|
||||||
|
DoQuadOverdraw(svPos, primId);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@9
|
@9
|
||||||
|
|||||||
@@ -694,4 +694,18 @@ void PS_Depth(PixelInput input)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if _PS_QuadOverdraw
|
||||||
|
|
||||||
|
#include "./Flax/Editor/QuadOverdraw.hlsl"
|
||||||
|
|
||||||
|
// Pixel Shader function for Quad Overdraw Pass (editor-only)
|
||||||
|
[earlydepthstencil]
|
||||||
|
META_PS(USE_EDITOR, FEATURE_LEVEL_SM5)
|
||||||
|
void PS_QuadOverdraw(float4 svPos : SV_Position, uint primId : SV_PrimitiveID)
|
||||||
|
{
|
||||||
|
DoQuadOverdraw(svPos, primId);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@9
|
@9
|
||||||
|
|||||||
@@ -594,7 +594,7 @@ void ClipLODTransition(PixelInput input)
|
|||||||
// Pixel Shader function for Depth Pass
|
// Pixel Shader function for Depth Pass
|
||||||
META_PS(true, FEATURE_LEVEL_ES2)
|
META_PS(true, FEATURE_LEVEL_ES2)
|
||||||
void PS_Depth(PixelInput input)
|
void PS_Depth(PixelInput input)
|
||||||
{
|
{
|
||||||
#if USE_DITHERED_LOD_TRANSITION
|
#if USE_DITHERED_LOD_TRANSITION
|
||||||
// LOD masking
|
// LOD masking
|
||||||
ClipLODTransition(input);
|
ClipLODTransition(input);
|
||||||
@@ -615,4 +615,18 @@ void PS_Depth(PixelInput input)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if _PS_QuadOverdraw
|
||||||
|
|
||||||
|
#include "./Flax/Editor/QuadOverdraw.hlsl"
|
||||||
|
|
||||||
|
// Pixel Shader function for Quad Overdraw Pass (editor-only)
|
||||||
|
[earlydepthstencil]
|
||||||
|
META_PS(USE_EDITOR, FEATURE_LEVEL_SM5)
|
||||||
|
void PS_QuadOverdraw(float4 svPos : SV_Position, uint primId : SV_PrimitiveID)
|
||||||
|
{
|
||||||
|
DoQuadOverdraw(svPos, primId);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@9
|
@9
|
||||||
|
|||||||
@@ -458,4 +458,18 @@ void PS_Depth(PixelInput input)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if _PS_QuadOverdraw
|
||||||
|
|
||||||
|
#include "./Flax/Editor/QuadOverdraw.hlsl"
|
||||||
|
|
||||||
|
// Pixel Shader function for Quad Overdraw Pass (editor-only)
|
||||||
|
[earlydepthstencil]
|
||||||
|
META_PS(USE_EDITOR, FEATURE_LEVEL_SM5)
|
||||||
|
void PS_QuadOverdraw(float4 svPos : SV_Position, uint primId : SV_PrimitiveID)
|
||||||
|
{
|
||||||
|
DoQuadOverdraw(svPos, primId);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@9
|
@9
|
||||||
|
|||||||
BIN
Content/Shaders/Editor/QuadOverdraw.flax
(Stored with Git LFS)
Normal file
BIN
Content/Shaders/Editor/QuadOverdraw.flax
(Stored with Git LFS)
Normal file
Binary file not shown.
@@ -1399,6 +1399,7 @@ namespace FlaxEditor.Viewport
|
|||||||
new ViewModeOptions(ViewMode.PhysicsColliders, "Physics Colliders"),
|
new ViewModeOptions(ViewMode.PhysicsColliders, "Physics Colliders"),
|
||||||
new ViewModeOptions(ViewMode.LODPreview, "LOD Preview"),
|
new ViewModeOptions(ViewMode.LODPreview, "LOD Preview"),
|
||||||
new ViewModeOptions(ViewMode.MaterialComplexity, "Material Complexity"),
|
new ViewModeOptions(ViewMode.MaterialComplexity, "Material Complexity"),
|
||||||
|
new ViewModeOptions(ViewMode.QuadOverdraw, "Quad Overdraw"),
|
||||||
};
|
};
|
||||||
|
|
||||||
private void WidgetCamSpeedShowHide(Control cm)
|
private void WidgetCamSpeedShowHide(Control cm)
|
||||||
|
|||||||
@@ -689,6 +689,12 @@ API_ENUM(Attributes="Flags") enum class DrawPass : int32
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
MotionVectors = 1 << 4,
|
MotionVectors = 1 << 4,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The debug quad overdraw rendering (editor-only).
|
||||||
|
/// </summary>
|
||||||
|
API_ENUM(Attributes="HideInEditor")
|
||||||
|
QuadOverdraw = 1 << 20,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The default set of draw passes for the scene objects.
|
/// The default set of draw passes for the scene objects.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -823,6 +829,11 @@ API_ENUM() enum class ViewMode
|
|||||||
/// Draw material shaders complexity to visualize performance of pixels rendering.
|
/// Draw material shaders complexity to visualize performance of pixels rendering.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
MaterialComplexity = 22,
|
MaterialComplexity = 22,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Draw geometry overdraw to visualize performance of pixels rendering.
|
||||||
|
/// </summary>
|
||||||
|
QuadOverdraw = 23,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ PACK_STRUCT(struct DeferredMaterialShaderData {
|
|||||||
|
|
||||||
DrawPass DeferredMaterialShader::GetDrawModes() const
|
DrawPass DeferredMaterialShader::GetDrawModes() const
|
||||||
{
|
{
|
||||||
return DrawPass::Depth | DrawPass::GBuffer | DrawPass::MotionVectors;
|
return DrawPass::Depth | DrawPass::GBuffer | DrawPass::MotionVectors | DrawPass::QuadOverdraw;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DeferredMaterialShader::CanUseLightmap() const
|
bool DeferredMaterialShader::CanUseLightmap() const
|
||||||
@@ -195,6 +195,17 @@ bool DeferredMaterialShader::Load()
|
|||||||
psDesc.PS = _shader->GetPS("PS_GBuffer");
|
psDesc.PS = _shader->GetPS("PS_GBuffer");
|
||||||
_cache.DefaultSkinned.Init(psDesc);
|
_cache.DefaultSkinned.Init(psDesc);
|
||||||
|
|
||||||
|
#if USE_EDITOR
|
||||||
|
// Quad Overdraw
|
||||||
|
psDesc.VS = _shader->GetVS("VS");
|
||||||
|
psDesc.PS = _shader->GetPS("PS_QuadOverdraw");
|
||||||
|
_cache.QuadOverdraw.Init(psDesc);
|
||||||
|
psDesc.VS = _shader->GetVS("VS", 1);
|
||||||
|
_cacheInstanced.Depth.Init(psDesc);
|
||||||
|
psDesc.VS = _shader->GetVS("VS_Skinned");
|
||||||
|
_cache.QuadOverdrawSkinned.Init(psDesc);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Motion Vectors pass
|
// Motion Vectors pass
|
||||||
psDesc.DepthWriteEnable = false;
|
psDesc.DepthWriteEnable = false;
|
||||||
psDesc.DepthTestEnable = true;
|
psDesc.DepthTestEnable = true;
|
||||||
|
|||||||
@@ -21,6 +21,10 @@ private:
|
|||||||
PipelineStateCache MotionVectors;
|
PipelineStateCache MotionVectors;
|
||||||
PipelineStateCache MotionVectorsSkinned;
|
PipelineStateCache MotionVectorsSkinned;
|
||||||
PipelineStateCache MotionVectorsSkinnedPerBone;
|
PipelineStateCache MotionVectorsSkinnedPerBone;
|
||||||
|
#if USE_EDITOR
|
||||||
|
PipelineStateCache QuadOverdraw;
|
||||||
|
PipelineStateCache QuadOverdrawSkinned;
|
||||||
|
#endif
|
||||||
|
|
||||||
FORCE_INLINE PipelineStateCache* GetPS(const DrawPass pass, const bool useLightmap, const bool useSkinning, const bool perBoneMotionBlur)
|
FORCE_INLINE PipelineStateCache* GetPS(const DrawPass pass, const bool useLightmap, const bool useSkinning, const bool perBoneMotionBlur)
|
||||||
{
|
{
|
||||||
@@ -32,6 +36,10 @@ private:
|
|||||||
return useLightmap ? &DefaultLightmap : (useSkinning ? &DefaultSkinned : &Default);
|
return useLightmap ? &DefaultLightmap : (useSkinning ? &DefaultSkinned : &Default);
|
||||||
case DrawPass::MotionVectors:
|
case DrawPass::MotionVectors:
|
||||||
return useSkinning ? (perBoneMotionBlur ? &MotionVectorsSkinnedPerBone : &MotionVectorsSkinned) : &MotionVectors;
|
return useSkinning ? (perBoneMotionBlur ? &MotionVectorsSkinnedPerBone : &MotionVectorsSkinned) : &MotionVectors;
|
||||||
|
#if USE_EDITOR
|
||||||
|
case DrawPass::QuadOverdraw:
|
||||||
|
return useSkinning ? &QuadOverdrawSkinned : &QuadOverdraw;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -46,6 +54,10 @@ private:
|
|||||||
DepthSkinned.Release();
|
DepthSkinned.Release();
|
||||||
MotionVectors.Release();
|
MotionVectors.Release();
|
||||||
MotionVectorsSkinned.Release();
|
MotionVectorsSkinned.Release();
|
||||||
|
#if USE_EDITOR
|
||||||
|
QuadOverdraw.Release();
|
||||||
|
QuadOverdrawSkinned.Release();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ void DeformableMaterialShader::Unload()
|
|||||||
|
|
||||||
bool DeformableMaterialShader::Load()
|
bool DeformableMaterialShader::Load()
|
||||||
{
|
{
|
||||||
_drawModes = DrawPass::Depth;
|
_drawModes = DrawPass::Depth | DrawPass::QuadOverdraw;
|
||||||
auto psDesc = GPUPipelineState::Description::Default;
|
auto psDesc = GPUPipelineState::Description::Default;
|
||||||
psDesc.DepthTestEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == 0;
|
psDesc.DepthTestEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == 0;
|
||||||
psDesc.DepthWriteEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthWrite) == 0;
|
psDesc.DepthWriteEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthWrite) == 0;
|
||||||
@@ -140,6 +140,13 @@ bool DeformableMaterialShader::Load()
|
|||||||
psDesc.HS = _shader->GetHS("HS");
|
psDesc.HS = _shader->GetHS("HS");
|
||||||
psDesc.DS = _shader->GetDS("DS");
|
psDesc.DS = _shader->GetDS("DS");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if USE_EDITOR
|
||||||
|
// Quad Overdraw
|
||||||
|
psDesc.VS = _shader->GetVS("VS_SplineModel");
|
||||||
|
psDesc.PS = _shader->GetPS("PS_QuadOverdraw");
|
||||||
|
_cache.QuadOverdraw.Init(psDesc);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (_info.BlendMode == MaterialBlendMode::Opaque)
|
if (_info.BlendMode == MaterialBlendMode::Opaque)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -15,6 +15,9 @@ private:
|
|||||||
{
|
{
|
||||||
PipelineStateCache Default;
|
PipelineStateCache Default;
|
||||||
PipelineStateCache Depth;
|
PipelineStateCache Depth;
|
||||||
|
#if USE_EDITOR
|
||||||
|
PipelineStateCache QuadOverdraw;
|
||||||
|
#endif
|
||||||
|
|
||||||
FORCE_INLINE PipelineStateCache* GetPS(const DrawPass pass)
|
FORCE_INLINE PipelineStateCache* GetPS(const DrawPass pass)
|
||||||
{
|
{
|
||||||
@@ -25,6 +28,10 @@ private:
|
|||||||
case DrawPass::GBuffer:
|
case DrawPass::GBuffer:
|
||||||
case DrawPass::Forward:
|
case DrawPass::Forward:
|
||||||
return &Default;
|
return &Default;
|
||||||
|
#if USE_EDITOR
|
||||||
|
case DrawPass::QuadOverdraw:
|
||||||
|
return &QuadOverdraw;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -34,6 +41,9 @@ private:
|
|||||||
{
|
{
|
||||||
Default.Release();
|
Default.Release();
|
||||||
Depth.Release();
|
Depth.Release();
|
||||||
|
#if USE_EDITOR
|
||||||
|
QuadOverdraw.Release();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ void ForwardMaterialShader::Unload()
|
|||||||
|
|
||||||
bool ForwardMaterialShader::Load()
|
bool ForwardMaterialShader::Load()
|
||||||
{
|
{
|
||||||
_drawModes = DrawPass::Depth | DrawPass::Forward;
|
_drawModes = DrawPass::Depth | DrawPass::Forward | DrawPass::QuadOverdraw;
|
||||||
|
|
||||||
auto psDesc = GPUPipelineState::Description::Default;
|
auto psDesc = GPUPipelineState::Description::Default;
|
||||||
psDesc.DepthTestEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == 0;
|
psDesc.DepthTestEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == 0;
|
||||||
@@ -168,6 +168,17 @@ bool ForwardMaterialShader::Load()
|
|||||||
psDesc.DS = _shader->GetDS("DS");
|
psDesc.DS = _shader->GetDS("DS");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if USE_EDITOR
|
||||||
|
// Quad Overdraw
|
||||||
|
psDesc.VS = _shader->GetVS("VS");
|
||||||
|
psDesc.PS = _shader->GetPS("PS_QuadOverdraw");
|
||||||
|
_cache.QuadOverdraw.Init(psDesc);
|
||||||
|
psDesc.VS = _shader->GetVS("VS", 1);
|
||||||
|
_cacheInstanced.Depth.Init(psDesc);
|
||||||
|
psDesc.VS = _shader->GetVS("VS_Skinned");
|
||||||
|
_cache.QuadOverdrawSkinned.Init(psDesc);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Check if use transparent distortion pass
|
// Check if use transparent distortion pass
|
||||||
if (_shader->HasShader("PS_Distortion"))
|
if (_shader->HasShader("PS_Distortion"))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -19,6 +19,10 @@ private:
|
|||||||
PipelineStateCache DepthSkinned;
|
PipelineStateCache DepthSkinned;
|
||||||
PipelineStateCache Distortion;
|
PipelineStateCache Distortion;
|
||||||
PipelineStateCache DistortionSkinned;
|
PipelineStateCache DistortionSkinned;
|
||||||
|
#if USE_EDITOR
|
||||||
|
PipelineStateCache QuadOverdraw;
|
||||||
|
PipelineStateCache QuadOverdrawSkinned;
|
||||||
|
#endif
|
||||||
|
|
||||||
FORCE_INLINE PipelineStateCache* GetPS(const DrawPass pass, const bool useSkinning)
|
FORCE_INLINE PipelineStateCache* GetPS(const DrawPass pass, const bool useSkinning)
|
||||||
{
|
{
|
||||||
@@ -30,6 +34,10 @@ private:
|
|||||||
return useSkinning ? &DistortionSkinned : &Distortion;
|
return useSkinning ? &DistortionSkinned : &Distortion;
|
||||||
case DrawPass::Forward:
|
case DrawPass::Forward:
|
||||||
return useSkinning ? &DefaultSkinned : &Default;
|
return useSkinning ? &DefaultSkinned : &Default;
|
||||||
|
#if USE_EDITOR
|
||||||
|
case DrawPass::QuadOverdraw:
|
||||||
|
return useSkinning ? &QuadOverdrawSkinned : &QuadOverdraw;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ void ParticleMaterialShader::Unload()
|
|||||||
|
|
||||||
bool ParticleMaterialShader::Load()
|
bool ParticleMaterialShader::Load()
|
||||||
{
|
{
|
||||||
_drawModes = DrawPass::Depth | DrawPass::Forward;
|
_drawModes = DrawPass::Depth | DrawPass::Forward | DrawPass::QuadOverdraw;
|
||||||
GPUPipelineState::Description psDesc = GPUPipelineState::Description::Default;
|
GPUPipelineState::Description psDesc = GPUPipelineState::Description::Default;
|
||||||
psDesc.DepthTestEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == 0;
|
psDesc.DepthTestEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == 0;
|
||||||
psDesc.DepthWriteEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthWrite) == 0;
|
psDesc.DepthWriteEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthWrite) == 0;
|
||||||
@@ -210,6 +210,17 @@ bool ParticleMaterialShader::Load()
|
|||||||
auto vsMesh = _shader->GetVS("VS_Model");
|
auto vsMesh = _shader->GetVS("VS_Model");
|
||||||
auto vsRibbon = _shader->GetVS("VS_Ribbon");
|
auto vsRibbon = _shader->GetVS("VS_Ribbon");
|
||||||
|
|
||||||
|
#if USE_EDITOR
|
||||||
|
// Quad Overdraw
|
||||||
|
psDesc.PS = _shader->GetPS("PS_QuadOverdraw");
|
||||||
|
psDesc.VS = vsSprite;
|
||||||
|
_cacheSprite.QuadOverdraw.Init(psDesc);
|
||||||
|
psDesc.VS = vsMesh;
|
||||||
|
_cacheModel.QuadOverdraw.Init(psDesc);
|
||||||
|
psDesc.VS = vsRibbon;
|
||||||
|
_cacheRibbon.QuadOverdraw.Init(psDesc);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Check if use transparent distortion pass
|
// Check if use transparent distortion pass
|
||||||
if (_shader->HasShader("PS_Distortion"))
|
if (_shader->HasShader("PS_Distortion"))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -16,6 +16,9 @@ private:
|
|||||||
PipelineStateCache Default;
|
PipelineStateCache Default;
|
||||||
PipelineStateCache Depth;
|
PipelineStateCache Depth;
|
||||||
PipelineStateCache Distortion;
|
PipelineStateCache Distortion;
|
||||||
|
#if USE_EDITOR
|
||||||
|
PipelineStateCache QuadOverdraw;
|
||||||
|
#endif
|
||||||
|
|
||||||
FORCE_INLINE PipelineStateCache* GetPS(const DrawPass pass)
|
FORCE_INLINE PipelineStateCache* GetPS(const DrawPass pass)
|
||||||
{
|
{
|
||||||
@@ -27,6 +30,8 @@ private:
|
|||||||
return &Distortion;
|
return &Distortion;
|
||||||
case DrawPass::Forward:
|
case DrawPass::Forward:
|
||||||
return &Default;
|
return &Default;
|
||||||
|
case DrawPass::QuadOverdraw:
|
||||||
|
return &QuadOverdraw;
|
||||||
default:
|
default:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -37,6 +42,9 @@ private:
|
|||||||
Default.Release();
|
Default.Release();
|
||||||
Depth.Release();
|
Depth.Release();
|
||||||
Distortion.Release();
|
Distortion.Release();
|
||||||
|
#if USE_EDITOR
|
||||||
|
QuadOverdraw.Release();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -183,6 +183,12 @@ bool TerrainMaterialShader::Load()
|
|||||||
// GBuffer Pass with lightmap (use pixel shader permutation for USE_LIGHTMAP=1)
|
// GBuffer Pass with lightmap (use pixel shader permutation for USE_LIGHTMAP=1)
|
||||||
psDesc.PS = _shader->GetPS("PS_GBuffer", 1);
|
psDesc.PS = _shader->GetPS("PS_GBuffer", 1);
|
||||||
_cache.DefaultLightmap.Init(psDesc);
|
_cache.DefaultLightmap.Init(psDesc);
|
||||||
|
|
||||||
|
#if USE_EDITOR
|
||||||
|
// Quad Overdraw
|
||||||
|
psDesc.PS = _shader->GetPS("PS_QuadOverdraw");
|
||||||
|
_cache.QuadOverdraw.Init(psDesc);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Depth Pass
|
// Depth Pass
|
||||||
psDesc.CullMode = CullMode::TwoSided;
|
psDesc.CullMode = CullMode::TwoSided;
|
||||||
|
|||||||
@@ -16,6 +16,9 @@ private:
|
|||||||
PipelineStateCache Default;
|
PipelineStateCache Default;
|
||||||
PipelineStateCache DefaultLightmap;
|
PipelineStateCache DefaultLightmap;
|
||||||
PipelineStateCache Depth;
|
PipelineStateCache Depth;
|
||||||
|
#if USE_EDITOR
|
||||||
|
PipelineStateCache QuadOverdraw;
|
||||||
|
#endif
|
||||||
|
|
||||||
FORCE_INLINE PipelineStateCache* GetPS(const DrawPass pass, const bool useLightmap)
|
FORCE_INLINE PipelineStateCache* GetPS(const DrawPass pass, const bool useLightmap)
|
||||||
{
|
{
|
||||||
@@ -25,6 +28,10 @@ private:
|
|||||||
return &Depth;
|
return &Depth;
|
||||||
case DrawPass::GBuffer:
|
case DrawPass::GBuffer:
|
||||||
return useLightmap ? &DefaultLightmap : &Default;
|
return useLightmap ? &DefaultLightmap : &Default;
|
||||||
|
#if USE_EDITOR
|
||||||
|
case DrawPass::QuadOverdraw:
|
||||||
|
return &QuadOverdraw;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -35,6 +42,9 @@ private:
|
|||||||
Default.Release();
|
Default.Release();
|
||||||
DefaultLightmap.Release();
|
DefaultLightmap.Release();
|
||||||
Depth.Release();
|
Depth.Release();
|
||||||
|
#if USE_EDITOR
|
||||||
|
QuadOverdraw.Release();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
158
Source/Engine/Renderer/Editor/QuadOverdrawPass.cpp
Normal file
158
Source/Engine/Renderer/Editor/QuadOverdrawPass.cpp
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
#if USE_EDITOR
|
||||||
|
|
||||||
|
#include "QuadOverdrawPass.h"
|
||||||
|
#include "Engine/Engine/Time.h"
|
||||||
|
#include "Engine/Content/Content.h"
|
||||||
|
#include "Engine/Content/Assets/Material.h"
|
||||||
|
#include "Engine/Level/Actors/Decal.h"
|
||||||
|
#include "Engine/Graphics/GPUDevice.h"
|
||||||
|
#include "Engine/Graphics/Shaders/GPUShader.h"
|
||||||
|
#include "Engine/Graphics/RenderTask.h"
|
||||||
|
#include "Engine/Graphics/RenderBuffers.h"
|
||||||
|
#include "Engine/Graphics/RenderTargetPool.h"
|
||||||
|
#include "Engine/Renderer/RenderList.h"
|
||||||
|
|
||||||
|
void QuadOverdrawPass::Render(RenderContext& renderContext, GPUContext* context, GPUTextureView* lightBuffer)
|
||||||
|
{
|
||||||
|
if (checkIfSkipPass())
|
||||||
|
{
|
||||||
|
context->Clear(lightBuffer, Color(0, Math::Sin(Time::Draw.UnscaledTime.GetTotalSeconds() * 5.0f) * 0.5f + 0.5f, 0, 1.0f));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
PROFILE_GPU_CPU("Quad Overdraw");
|
||||||
|
|
||||||
|
// Setup resources
|
||||||
|
const int32 width = renderContext.Buffers->GetWidth();
|
||||||
|
const int32 height = renderContext.Buffers->GetHeight();
|
||||||
|
auto tempDesc = GPUTextureDescription::New2D(width >> 1, height >> 1, PixelFormat::R32_UInt, GPUTextureFlags::ShaderResource | GPUTextureFlags::UnorderedAccess);
|
||||||
|
auto lockTexture = RenderTargetPool::Get(tempDesc);
|
||||||
|
auto overdrawTexture = RenderTargetPool::Get(tempDesc);
|
||||||
|
auto liveCountTexture = RenderTargetPool::Get(tempDesc);
|
||||||
|
|
||||||
|
// Clear buffers
|
||||||
|
uint32 clearValueUINT[4] = { 0 };
|
||||||
|
clearValueUINT[0] = 0xffffffff;
|
||||||
|
context->ClearUA(lockTexture, clearValueUINT);
|
||||||
|
clearValueUINT[0] = 0x00000000;
|
||||||
|
context->ClearUA(overdrawTexture, clearValueUINT);
|
||||||
|
context->ClearUA(liveCountTexture, clearValueUINT);
|
||||||
|
context->ClearDepth(*renderContext.Buffers->DepthBuffer);
|
||||||
|
|
||||||
|
// Draw quad overdraw stats into UAVs
|
||||||
|
context->BindUA(0, lockTexture->View());
|
||||||
|
context->BindUA(1, overdrawTexture->View());
|
||||||
|
context->BindUA(2, liveCountTexture->View());
|
||||||
|
DrawCall drawCall;
|
||||||
|
Platform::MemoryClear(&drawCall, sizeof(DrawCall));
|
||||||
|
drawCall.PerInstanceRandom = 1.0f;
|
||||||
|
MaterialBase::BindParameters bindParams(context, renderContext, drawCall);
|
||||||
|
renderContext.View.Pass = DrawPass::QuadOverdraw;
|
||||||
|
context->SetRenderTarget(*renderContext.Buffers->DepthBuffer, (GPUTextureView*)nullptr);
|
||||||
|
renderContext.List->ExecuteDrawCalls(renderContext, DrawCallsListType::GBuffer);
|
||||||
|
auto boxModel = Content::LoadAsyncInternal<Model>(TEXT("Engine/Models/SimpleBox"));
|
||||||
|
auto defaultMaterial = GPUDevice::Instance->GetDefaultMaterial();
|
||||||
|
if (boxModel && boxModel->CanBeRendered() && defaultMaterial && defaultMaterial->IsReady())
|
||||||
|
{
|
||||||
|
// Draw decals
|
||||||
|
for (int32 i = 0; i < renderContext.List->Decals.Count(); i++)
|
||||||
|
{
|
||||||
|
const auto decal = renderContext.List->Decals[i];
|
||||||
|
ASSERT(decal && decal->Material);
|
||||||
|
decal->GetWorld(&drawCall.World);
|
||||||
|
drawCall.ObjectPosition = drawCall.World.GetTranslation();
|
||||||
|
drawCall.PerInstanceRandom = decal->GetPerInstanceRandom();
|
||||||
|
defaultMaterial->Bind(bindParams);
|
||||||
|
boxModel->Render(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
renderContext.List->ExecuteDrawCalls(renderContext, DrawCallsListType::GBufferNoDecals);
|
||||||
|
auto skyModel = Content::LoadAsyncInternal<Model>(TEXT("Engine/Models/Sphere"));
|
||||||
|
auto skyMaterial = Content::LoadAsyncInternal<Material>(TEXT("Engine/SkyboxMaterial"));
|
||||||
|
if (renderContext.List->Sky && skyModel && skyModel->CanBeRendered() && skyMaterial && skyMaterial->IsReady())
|
||||||
|
{
|
||||||
|
// Draw sky
|
||||||
|
auto box = skyModel->GetBox();
|
||||||
|
Matrix m1, m2;
|
||||||
|
Matrix::Scaling(renderContext.View.Far / (box.GetSize().Y * 0.5f) * 0.95f, m1);
|
||||||
|
Matrix::CreateWorld(renderContext.View.Position, Vector3::Up, Vector3::Backward, m2);
|
||||||
|
m1 *= m2;
|
||||||
|
drawCall.World = m1;
|
||||||
|
drawCall.ObjectPosition = drawCall.World.GetTranslation();
|
||||||
|
drawCall.WorldDeterminantSign = Math::FloatSelect(drawCall.World.RotDeterminant(), 1, -1);
|
||||||
|
skyMaterial->Bind(bindParams);
|
||||||
|
skyModel->Render(context);
|
||||||
|
}
|
||||||
|
GPUTexture* depthBuffer = renderContext.Buffers->DepthBuffer;
|
||||||
|
GPUTextureView* readOnlyDepthBuffer = depthBuffer->View();
|
||||||
|
if (depthBuffer->GetDescription().Flags & GPUTextureFlags::ReadOnlyDepthView)
|
||||||
|
readOnlyDepthBuffer = depthBuffer->ViewReadOnlyDepth();
|
||||||
|
context->ResetSR();
|
||||||
|
context->ResetRenderTarget();
|
||||||
|
context->SetRenderTarget(readOnlyDepthBuffer, (GPUTextureView*)nullptr);
|
||||||
|
renderContext.List->ExecuteDrawCalls(renderContext, DrawCallsListType::Forward);
|
||||||
|
renderContext.List->ExecuteDrawCalls(renderContext, DrawCallsListType::Distortion);
|
||||||
|
// TODO: draw volumetric particles
|
||||||
|
context->ResetRenderTarget();
|
||||||
|
context->ResetUA();
|
||||||
|
context->ResetSR();
|
||||||
|
|
||||||
|
// Convert stats into debug colors
|
||||||
|
context->BindSR(0, overdrawTexture->View());
|
||||||
|
context->SetRenderTarget(lightBuffer);
|
||||||
|
context->SetState(_ps);
|
||||||
|
context->DrawFullscreenTriangle();
|
||||||
|
|
||||||
|
// Free resources
|
||||||
|
RenderTargetPool::Release(liveCountTexture);
|
||||||
|
RenderTargetPool::Release(overdrawTexture);
|
||||||
|
RenderTargetPool::Release(lockTexture);
|
||||||
|
}
|
||||||
|
|
||||||
|
String QuadOverdrawPass::ToString() const
|
||||||
|
{
|
||||||
|
return TEXT("QuadOverdrawPass");
|
||||||
|
}
|
||||||
|
|
||||||
|
void QuadOverdrawPass::Dispose()
|
||||||
|
{
|
||||||
|
// Base
|
||||||
|
RendererPass::Dispose();
|
||||||
|
|
||||||
|
SAFE_DELETE_GPU_RESOURCE(_ps);
|
||||||
|
_shader = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QuadOverdrawPass::setupResources()
|
||||||
|
{
|
||||||
|
if (GPUDevice::Instance->GetFeatureLevel() < FeatureLevel::SM5)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!_shader)
|
||||||
|
{
|
||||||
|
_shader = Content::LoadAsyncInternal<Shader>(TEXT("Shaders/Editor/QuadOverdraw"));
|
||||||
|
if (!_shader)
|
||||||
|
return true;
|
||||||
|
#if COMPILE_WITH_DEV_ENV
|
||||||
|
_shader.Get()->OnReloading.Bind<QuadOverdrawPass, &QuadOverdrawPass::OnShaderReloading>(this);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if (!_shader->IsLoaded())
|
||||||
|
return true;
|
||||||
|
const auto shader = _shader->GetShader();
|
||||||
|
|
||||||
|
GPUPipelineState::Description psDesc = GPUPipelineState::Description::DefaultFullscreenTriangle;
|
||||||
|
if (!_ps)
|
||||||
|
_ps = GPUDevice::Instance->CreatePipelineState();
|
||||||
|
if (!_ps->IsValid())
|
||||||
|
{
|
||||||
|
psDesc.PS = shader->GetPS("PS");
|
||||||
|
if (_ps->Init(psDesc))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
46
Source/Engine/Renderer/Editor/QuadOverdrawPass.h
Normal file
46
Source/Engine/Renderer/Editor/QuadOverdrawPass.h
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if USE_EDITOR
|
||||||
|
|
||||||
|
#include "../RendererPass.h"
|
||||||
|
|
||||||
|
class GPUContext;
|
||||||
|
class GPUTextureView;
|
||||||
|
class GPUPipelineState;
|
||||||
|
struct RenderContext;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Rendering geometry overdraw to visualize performance of pixels rendering in editor.
|
||||||
|
/// </summary>
|
||||||
|
class QuadOverdrawPass : public RendererPass<QuadOverdrawPass>
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
AssetReference<Shader> _shader;
|
||||||
|
GPUPipelineState* _ps = nullptr;
|
||||||
|
|
||||||
|
#if COMPILE_WITH_DEV_ENV
|
||||||
|
void OnShaderReloading(Asset* obj)
|
||||||
|
{
|
||||||
|
_ps->ReleaseGPU();
|
||||||
|
invalidateResources();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void Render(RenderContext& renderContext, GPUContext* context, GPUTextureView* lightBuffer);
|
||||||
|
|
||||||
|
// [RendererPass]
|
||||||
|
String ToString() const override;
|
||||||
|
void Dispose() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// [RendererPass]
|
||||||
|
bool setupResources() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -30,6 +30,7 @@
|
|||||||
#include "Engine/Level/Level.h"
|
#include "Engine/Level/Level.h"
|
||||||
#if USE_EDITOR
|
#if USE_EDITOR
|
||||||
#include "Editor/Editor.h"
|
#include "Editor/Editor.h"
|
||||||
|
#include "Editor/QuadOverdrawPass.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if USE_EDITOR
|
#if USE_EDITOR
|
||||||
@@ -80,6 +81,9 @@ bool RendererService::Init()
|
|||||||
PassList.Add(TAA::Instance());
|
PassList.Add(TAA::Instance());
|
||||||
PassList.Add(SMAA::Instance());
|
PassList.Add(SMAA::Instance());
|
||||||
PassList.Add(HistogramPass::Instance());
|
PassList.Add(HistogramPass::Instance());
|
||||||
|
#if USE_EDITOR
|
||||||
|
PassList.Add(QuadOverdrawPass::Instance());
|
||||||
|
#endif
|
||||||
|
|
||||||
// Skip when using Null renderer
|
// Skip when using Null renderer
|
||||||
if (GPUDevice::Instance->GetRendererType() == RendererType::Null)
|
if (GPUDevice::Instance->GetRendererType() == RendererType::Null)
|
||||||
@@ -320,6 +324,19 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext)
|
|||||||
auto tempDesc = GPUTextureDescription::New2D(renderContext.Buffers->GetWidth(), renderContext.Buffers->GetHeight(), PixelFormat::R11G11B10_Float);
|
auto tempDesc = GPUTextureDescription::New2D(renderContext.Buffers->GetWidth(), renderContext.Buffers->GetHeight(), PixelFormat::R11G11B10_Float);
|
||||||
auto lightBuffer = RenderTargetPool::Get(tempDesc);
|
auto lightBuffer = RenderTargetPool::Get(tempDesc);
|
||||||
|
|
||||||
|
#if USE_EDITOR
|
||||||
|
if (renderContext.View.Mode == ViewMode::QuadOverdraw)
|
||||||
|
{
|
||||||
|
QuadOverdrawPass::Instance()->Render(renderContext, context, lightBuffer->View());
|
||||||
|
context->ResetRenderTarget();
|
||||||
|
context->SetRenderTarget(task->GetOutputView());
|
||||||
|
context->SetViewportAndScissors(task->GetOutputViewport());
|
||||||
|
context->Draw(lightBuffer);
|
||||||
|
RenderTargetPool::Release(lightBuffer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Fill GBuffer
|
// Fill GBuffer
|
||||||
GBufferPass::Instance()->Fill(renderContext, lightBuffer->View());
|
GBufferPass::Instance()->Fill(renderContext, lightBuffer->View());
|
||||||
|
|
||||||
|
|||||||
48
Source/Shaders/Editor/QuadOverdraw.hlsl
Normal file
48
Source/Shaders/Editor/QuadOverdraw.hlsl
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
// [Quad Overdraw implementation based on https://blog.selfshadow.com/2012/11/12/counting-quads/ by Stephen Hill]
|
||||||
|
#ifndef __QUAD_OVERDRAW__
|
||||||
|
#define __QUAD_OVERDRAW__
|
||||||
|
|
||||||
|
RWTexture2D<uint> lockUAV : register(u0);
|
||||||
|
RWTexture2D<uint> overdrawUAV : register(u1);
|
||||||
|
RWTexture2D<uint> liveCountUAV : register(u2);
|
||||||
|
|
||||||
|
void DoQuadOverdraw(float4 svPos, uint primId)
|
||||||
|
{
|
||||||
|
uint2 quad = svPos.xy * 0.5;
|
||||||
|
uint prevID;
|
||||||
|
uint unlockedID = 0xffffffff;
|
||||||
|
bool processed = false;
|
||||||
|
int lockCount = 0;
|
||||||
|
int pixelCount = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < 64; i++)
|
||||||
|
{
|
||||||
|
if (!processed)
|
||||||
|
InterlockedCompareExchange(lockUAV[quad], unlockedID, primId, prevID);
|
||||||
|
[branch]
|
||||||
|
if (prevID == unlockedID)
|
||||||
|
{
|
||||||
|
if (++lockCount == 4)
|
||||||
|
{
|
||||||
|
// Retrieve live pixel count (minus 1) in quad
|
||||||
|
InterlockedAnd(liveCountUAV[quad], 0, pixelCount);
|
||||||
|
|
||||||
|
// Unlock for other quads
|
||||||
|
InterlockedExchange(lockUAV[quad], unlockedID, prevID);
|
||||||
|
}
|
||||||
|
processed = true;
|
||||||
|
}
|
||||||
|
if (prevID == primId && !processed)
|
||||||
|
{
|
||||||
|
InterlockedAdd(liveCountUAV[quad], 1);
|
||||||
|
processed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lockCount)
|
||||||
|
{
|
||||||
|
InterlockedAdd(overdrawUAV[quad], 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
34
Source/Shaders/Editor/QuadOverdraw.shader
Normal file
34
Source/Shaders/Editor/QuadOverdraw.shader
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
#include "./Flax/Common.hlsl"
|
||||||
|
|
||||||
|
// [Quad Overdraw implementation based on https://blog.selfshadow.com/2012/11/12/counting-quads/ by Stephen Hill]
|
||||||
|
|
||||||
|
Texture2D<uint> overdrawSRV : register(t0);
|
||||||
|
|
||||||
|
float4 ToColour(uint v)
|
||||||
|
{
|
||||||
|
const uint nbColours = 10;
|
||||||
|
const float4 colours[nbColours] =
|
||||||
|
{
|
||||||
|
float4(0, 0, 0, 255),
|
||||||
|
float4(2, 147, 25, 255),
|
||||||
|
float4(0, 255, 149, 255),
|
||||||
|
float4(0, 255, 253, 255),
|
||||||
|
float4(142, 250, 0, 255),
|
||||||
|
float4(225, 251, 0, 255),
|
||||||
|
float4(225, 147, 0, 255),
|
||||||
|
float4(225, 38, 0, 255),
|
||||||
|
float4(148, 17, 0, 255),
|
||||||
|
float4(255, 255, 255, 255)
|
||||||
|
};
|
||||||
|
return colours[min(v, nbColours - 1)] / 255.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
META_PS(true, FEATURE_LEVEL_ES2)
|
||||||
|
float4 PS(float4 svPos : SV_POSITION) : SV_Target
|
||||||
|
{
|
||||||
|
uint2 quad = svPos.xy * 0.5;
|
||||||
|
uint overdraw = overdrawSRV[quad];
|
||||||
|
return ToColour(overdraw);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user