2
0
Эх сурвалжийг харах

Simplified renderpath depth stencil management, by ensuring that Renderer does not allocate multiple depth buffers of the same size.
Added forward renderpath which also outputs a readable linear depth texture, and depth-only shaders.

Lasse Öörni 13 жил өмнө
parent
commit
c0d669ede3

+ 11 - 0
Bin/CoreData/RenderPaths/ForwardDepth.xml

@@ -0,0 +1,11 @@
+<renderpath>
+    <rendertarget name="depth" format="lineardepth" />
+    <command type="clear" color="1 1 1 1" depth="1.0" output="depth" />
+    <command type="scenepass" pass="depth" output="depth" />
+    <command type="clear" color="fog" depth="1.0" stencil="0" />
+    <command type="scenepass" pass="base" vertexlights="true" />
+    <command type="forwardlights" />
+    <command type="scenepass" pass="prealpha" sort="state" />
+    <command type="scenepass" pass="alpha" usescissor="true" vertexlights="true" sort="backtofront" />
+    <command type="scenepass" pass="postalpha" sort="backtofront" />
+</renderpath>

+ 15 - 0
Bin/CoreData/Shaders/GLSL/Depth.frag

@@ -0,0 +1,15 @@
+#include "Uniforms.frag"
+#include "Samplers.frag"
+
+varying vec3 vTexCoord;
+
+void main()
+{
+    #ifdef ALPHAMASK
+        float alpha = texture2D(sDiffMap, vTexCoord.xy).a;
+        if (alpha < 0.5)
+            discard;
+    #endif
+
+    gl_FragColor = vec4(EncodeDepth(vTexCoord.z), 1.0);
+}

+ 13 - 0
Bin/CoreData/Shaders/GLSL/Depth.vert

@@ -0,0 +1,13 @@
+#include "Uniforms.vert"
+#include "Transform.vert"
+
+varying vec3 vTexCoord;
+
+void main()
+{
+    mat4 modelMatrix = iModelMatrix;
+    vec3 worldPos = GetWorldPos(modelMatrix);
+    gl_Position = GetClipPos(worldPos);
+    vTexCoord = vec3(GetTexCoord(iTexCoord), GetDepth(gl_Position));
+}
+

+ 9 - 0
Bin/CoreData/Shaders/GLSL/Depth.xml

@@ -0,0 +1,9 @@
+<shaders>
+    <shader type="vs">
+        <variation name="" />
+        <variation name="Skinned" define="SKINNED" />
+    </shader>
+    <shader type="ps">
+        <option name="AlphaMask" define="ALPHAMASK" />
+    </shader>
+</shaders>

+ 34 - 0
Bin/CoreData/Shaders/HLSL/Depth.hlsl

@@ -0,0 +1,34 @@
+#include "Uniforms.hlsl"
+#include "Samplers.hlsl"
+#include "Transform.hlsl"
+
+void VS(float4 iPos : POSITION,
+    #ifdef SKINNED
+        float4 iBlendWeights : BLENDWEIGHT,
+        int4 iBlendIndices : BLENDINDICES,
+    #endif
+    #ifdef INSTANCED
+        float4x3 iModelInstance : TEXCOORD2,
+    #endif
+    float2 iTexCoord : TEXCOORD0,
+    out float3 oTexCoord : TEXCOORD0,
+    out float4 oPos : POSITION)
+{
+    float4x3 modelMatrix = iModelMatrix;
+    float3 worldPos = GetWorldPos(modelMatrix);
+    oPos = GetClipPos(worldPos);
+    oTexCoord = float3(GetTexCoord(iTexCoord), GetDepth(oPos));
+}
+
+void PS(
+    float3 iTexCoord : TEXCOORD0,
+    out float4 oColor : COLOR0)
+{
+    #ifdef ALPHAMASK
+        float alpha = tex2D(sDiffMap, iTexCoord.xy).a;
+        if (alpha < 0.5)
+            discard;
+    #endif
+
+    oColor = iTexCoord.z;
+}

+ 10 - 0
Bin/CoreData/Shaders/HLSL/Depth.xml

@@ -0,0 +1,10 @@
+<shaders>
+    <shader type="vs">
+        <variation name="" />
+        <variation name="Skinned" define="SKINNED" />
+        <variation name="Instanced" define="INSTANCED" require="SM3" />
+    </shader>
+    <shader type="ps">
+        <option name="AlphaMask" define="ALPHAMASK" />
+    </shader>
+</shaders>

+ 1 - 0
Bin/CoreData/Techniques/Diff.xml

@@ -5,5 +5,6 @@
     <pass name="prepass" vs="LitSolid" ps="LitSolid_DiffPrepass" />
     <pass name="material" vs="LitSolid" ps="LitSolid_DiffMaterial" depthtest="equal" depthwrite="false" />
     <pass name="deferred" vs="LitSolid" ps="LitSolid_DiffDeferred" />
+    <pass name="depth" vs="Depth" ps="Depth" />
     <pass name="shadow" vs="Shadow" ps="Shadow" />
 </technique>

+ 1 - 1
Bin/CoreData/Techniques/DiffAdd.xml

@@ -1,3 +1,3 @@
 <technique>
-    <pass name="base" vs="Unlit" ps="Unlit_Diff" depthwrite="false" blend="add" />
+    <pass name="alpha" vs="Unlit" ps="Unlit_Diff" depthwrite="false" blend="add" />
 </technique>

+ 1 - 0
Bin/CoreData/Techniques/DiffAlphaMask.xml

@@ -5,5 +5,6 @@
     <pass name="prepass" vs="LitSolid" ps="LitSolid_DiffAlphaMaskPrepass" alphamask="true" />
     <pass name="material" vs="LitSolid" ps="LitSolid_DiffAlphaMaskMaterial" depthtest="equal" depthwrite="false" alphamask="true" />
     <pass name="deferred" vs="LitSolid" ps="LitSolid_DiffAlphaMaskDeferred" alphamask="true" />
+    <pass name="depth" vs="Depth" ps="Depth_AlphaMask" alphamask="true" />
     <pass name="shadow" vs="Shadow" ps="Shadow_AlphaMask" alphamask="true" />
 </technique>

+ 1 - 0
Bin/CoreData/Techniques/DiffEnvCube.xml

@@ -4,5 +4,6 @@
     <pass name="prepass" vs="LitSolid" ps="LitSolid_DiffPrepass" />
     <pass name="material" vs="LitSolid_EnvCube" ps="LitSolid_DiffEnvCubeMaterial" depthtest="equal" depthwrite="false" />
     <pass name="deferred" vs="LitSolid_EnvCube" ps="LitSolid_DiffEnvCubeDeferred" />
+    <pass name="depth" vs="Depth" ps="Depth" />
     <pass name="shadow" vs="Shadow" ps="Shadow" />
 </technique>

+ 1 - 0
Bin/CoreData/Techniques/DiffNormal.xml

@@ -5,5 +5,6 @@
     <pass name="prepass" vs="LitSolid_Normal" ps="LitSolid_DiffNormalPrepass" />
     <pass name="material" vs="LitSolid" ps="LitSolid_DiffMaterial" depthtest="equal" depthwrite="false" />
     <pass name="deferred" vs="LitSolid_Normal" ps="LitSolid_DiffNormalDeferred" />
+    <pass name="depth" vs="Depth" ps="Depth" />
     <pass name="shadow" vs="Shadow" ps="Shadow" />
 </technique>

+ 1 - 0
Bin/CoreData/Techniques/DiffNormalAlphaMask.xml

@@ -5,5 +5,6 @@
     <pass name="prepass" vs="LitSolid_Normal" ps="LitSolid_DiffNormalAlphaMaskPrepass" alphamask="true" />
     <pass name="material" vs="LitSolid" ps="LitSolid_DiffAlphaMaskMaterial" depthtest="equal" depthwrite="false" alphamask="true" />
     <pass name="deferred" vs="LitSolid_Normal" ps="LitSolid_DiffNormalAlphaMaskDeferred" alphamask="true" />
+    <pass name="depth" vs="Depth" ps="Depth_AlphaMask" alphamask="true" />
     <pass name="shadow" vs="Shadow" ps="Shadow_AlphaMask" alphamask="true" />
 </technique>

+ 1 - 0
Bin/CoreData/Techniques/DiffNormalEnvCube.xml

@@ -4,5 +4,6 @@
     <pass name="prepass" vs="LitSolid_Normal" ps="LitSolid_DiffNormalPrepass" />
     <pass name="material" vs="LitSolid_NormalEnvCube" ps="LitSolid_DiffNormalEnvCubeMaterial" depthtest="equal" depthwrite="false" />
     <pass name="deferred" vs="LitSolid_NormalEnvCube" ps="LitSolid_DiffNormalEnvCubeDeferred" />
+    <pass name="depth" vs="Depth" ps="Depth" />
     <pass name="shadow" vs="Shadow" ps="Shadow" />
 </technique>

+ 1 - 0
Bin/CoreData/Techniques/DiffNormalSpec.xml

@@ -5,5 +5,6 @@
     <pass name="prepass" vs="LitSolid_Normal" ps="LitSolid_DiffNormalSpecMapPrepass" />
     <pass name="material" vs="LitSolid" ps="LitSolid_DiffSpecMapMaterial" depthtest="equal" depthwrite="false" />
     <pass name="deferred" vs="LitSolid_Normal" ps="LitSolid_DiffNormalSpecMapDeferred" />
+    <pass name="depth" vs="Depth" ps="Depth" />
     <pass name="shadow" vs="Shadow" ps="Shadow" />
 </technique>

+ 1 - 0
Bin/CoreData/Techniques/DiffNormalSpecAlphaMask.xml

@@ -5,5 +5,6 @@
     <pass name="prepass" vs="LitSolid_Normal" ps="LitSolid_DiffNormalSpecMapAlphaMaskPrepass" alphamask="true" />
     <pass name="material" vs="LitSolid" ps="LitSolid_DiffSpecMapAlphaMaskMaterial" depthtest="equal" depthwrite="false" alphamask="true" />
     <pass name="deferred" vs="LitSolid_Normal" ps="LitSolid_DiffNormalSpecMapAlphaMaskDeferred" alphamask="true" />
+    <pass name="depth" vs="Depth" ps="Depth_AlphaMask" alphamask="true" />
     <pass name="shadow" vs="Shadow" ps="Shadow_AlphaMask" alphamask="true" />
 </technique>

+ 1 - 0
Bin/CoreData/Techniques/DiffSpec.xml

@@ -5,5 +5,6 @@
     <pass name="prepass" vs="LitSolid" ps="LitSolid_DiffSpecMapPrepass" />
     <pass name="material" vs="LitSolid" ps="LitSolid_DiffSpecMapMaterial" depthtest="equal" depthwrite="false" />
     <pass name="deferred" vs="LitSolid" ps="LitSolid_DiffSpecMapDeferred" />
+    <pass name="depth" vs="Depth" ps="Depth" />
     <pass name="shadow" vs="Shadow" ps="Shadow" />
 </technique>

+ 1 - 0
Bin/CoreData/Techniques/DiffSpecAlphaMask.xml

@@ -5,5 +5,6 @@
     <pass name="prepass" vs="LitSolid" ps="LitSolid_DiffSpecMapAlphaMaskPrepass" alphamask="true" />
     <pass name="material" vs="LitSolid" ps="LitSolid_DiffSpecMapAlphaMaskMaterial" depthtest="equal" depthwrite="false" alphamask="true" />
     <pass name="deferred" vs="LitSolid" ps="LitSolid_DiffSpecMapAlphaMaskDeferred" alphamask="true" />
+    <pass name="depth" vs="Depth" ps="Depth_AlphaMask" alphamask="true" />
     <pass name="shadow" vs="Shadow" ps="Shadow_AlphaMask" alphamask="true" />
 </technique>

+ 1 - 0
Bin/CoreData/Techniques/NoTexture.xml

@@ -5,5 +5,6 @@
     <pass name="prepass" vs="LitSolid" ps="LitSolid_Prepass" />
     <pass name="material" vs="LitSolid" ps="LitSolid_Material" depthtest="equal" depthwrite="false" />
     <pass name="deferred" vs="LitSolid" ps="LitSolid_Deferred" />
+    <pass name="depth" vs="Depth" ps="Depth" />
     <pass name="shadow" vs="Shadow" ps="Shadow" />
 </technique>

+ 1 - 0
Bin/CoreData/Techniques/NoTextureEnvCube.xml

@@ -4,5 +4,6 @@
     <pass name="prepass" vs="LitSolid" ps="LitSolid_Prepass" />
     <pass name="material" vs="LitSolid_EnvCube" ps="LitSolid_EnvCubeMaterial" depthtest="equal" depthwrite="false" />
     <pass name="deferred" vs="LitSolid_EnvCube" ps="LitSolid_EnvCubeDeferred" />
+    <pass name="depth" vs="Depth" ps="Depth" />
     <pass name="shadow" vs="Shadow" ps="Shadow" />
 </technique>

+ 1 - 0
Bin/CoreData/Techniques/TerrainBlend.xml

@@ -5,5 +5,6 @@
     <pass name="prepass" vs="TerrainBlend" ps="TerrainBlend_Prepass" />
     <pass name="material" vs="TerrainBlend" ps="TerrainBlend_Material" depthtest="equal" depthwrite="false" />
     <pass name="deferred" vs="TerrainBlend" ps="TerrainBlend_Deferred" />
+    <pass name="depth" vs="Depth" ps="Depth" />
     <pass name="shadow" vs="Shadow" ps="Shadow" />
 </technique>

+ 6 - 2
Engine/Graphics/Renderer.cpp

@@ -936,7 +936,11 @@ Texture2D* Renderer::GetScreenBuffer(int width, int height, unsigned format, boo
     if (screenBuffers_.Find(searchKey) == screenBuffers_.End())
         screenBufferAllocations_[searchKey] = 0;
     
-    unsigned allocations = screenBufferAllocations_[searchKey]++;
+    // Reuse depth-stencil buffers whenever the size matches, instead of allocating new
+    unsigned allocations = screenBufferAllocations_[searchKey];
+    if(!depthStencil)
+        ++screenBufferAllocations_[searchKey];
+    
     if (allocations >= screenBuffers_[searchKey].Size())
     {
         SharedPtr<Texture2D> newBuffer(new Texture2D(context_));
@@ -960,7 +964,7 @@ RenderSurface* Renderer::GetDepthStencil(int width, int height)
 {
     // Return the default depth-stencil surface if applicable
     // (when using OpenGL Graphics will allocate right size surfaces on demand to emulate Direct3D9)
-    if (width <= graphics_->GetWidth() && height <= graphics_->GetHeight() && graphics_->GetMultiSample() <= 1)
+    if (width == graphics_->GetWidth() && height == graphics_->GetHeight() && graphics_->GetMultiSample() <= 1)
         return 0;
     else
         return GetScreenBuffer(width, height, Graphics::GetDepthStencilFormat())->GetRenderSurface();

+ 7 - 19
Engine/Graphics/View.cpp

@@ -298,7 +298,6 @@ bool View::Define(RenderSurface* renderTarget, Viewport* viewport)
     camera_ = camera;
     cameraNode_ = camera->GetNode();
     renderTarget_ = renderTarget;
-    depthStencil_ = GetDepthStencil(renderTarget_);
     renderPath_ = viewport->GetRenderPath();
     
     // Make sure that all necessary batch queues exist
@@ -484,7 +483,7 @@ void View::Render()
     
     // Run framebuffer blitting if necessary
     if (screenBuffers_.Size() && currentRenderTarget_ != renderTarget_)
-        BlitFramebuffer(static_cast<Texture2D*>(currentRenderTarget_->GetParentTexture()), renderTarget_, depthStencil_, true);
+        BlitFramebuffer(static_cast<Texture2D*>(currentRenderTarget_->GetParentTexture()), renderTarget_, true);
     
     // If this is a main view, draw the associated debug geometry now
     if (!renderTarget_)
@@ -1177,8 +1176,7 @@ void View::ExecuteRenderPathCommands()
                     // If this is a scene render pass, must copy the previous viewport contents now
                     if (command.type_ == CMD_SCENEPASS && !needResolve)
                     {
-                        BlitFramebuffer(screenBuffers_[readBuffer_], screenBuffers_[writeBuffer_]->GetRenderSurface(),
-                            screenBufferDepthStencil_, false);
+                        BlitFramebuffer(screenBuffers_[readBuffer_], screenBuffers_[writeBuffer_]->GetRenderSurface(), false);
                     }
                     
                 }
@@ -1194,24 +1192,15 @@ void View::ExecuteRenderPathCommands()
             
             // Check which rendertarget will be used on this pass
             if (screenBuffers_.Size() && !needResolve)
-            {
                 currentRenderTarget_ = screenBuffers_[writeBuffer_]->GetRenderSurface();
-                currentDepthStencil_ = screenBufferDepthStencil_;
-            }
             else
-            {
                 currentRenderTarget_ = renderTarget_;
-                currentDepthStencil_ = depthStencil_;
-            }
             
             // Optimization: if the last command is a quad with output to the viewport, do not use the screenbuffers,
             // but the viewport directly. This saves the extra copy
             if (screenBuffers_.Size() && i == lastCommandIndex && command.type_ == CMD_QUAD && command.outputs_.Size() == 1 &&
                 !command.outputs_[0].Compare("viewport", false))
-            {
                 currentRenderTarget_ = renderTarget_;
-                currentDepthStencil_ = depthStencil_;
-            }
             
             switch (command.type_)
             {
@@ -1311,10 +1300,11 @@ void View::ExecuteRenderPathCommands()
         }
     }
     
+    // After executing all commands, reset rendertarget for debug geometry rendering
     graphics_->SetRenderTarget(0, renderTarget_);
     for (unsigned i = 1; i < MAX_RENDERTARGETS; ++i)
         graphics_->SetRenderTarget(i, (RenderSurface*)0);
-    graphics_->SetDepthStencil(depthStencil_);
+    graphics_->SetDepthStencil(GetDepthStencil(renderTarget_));
     graphics_->SetViewport(viewRect_);
     graphics_->SetFillMode(FILL_SOLID);
 }
@@ -1345,7 +1335,7 @@ void View::SetRenderTargets(const RenderPathCommand& command)
         ++index;
     }
     
-    graphics_->SetDepthStencil(currentDepthStencil_);
+    graphics_->SetDepthStencil(GetDepthStencil(graphics_->GetRenderTarget(0)));
     graphics_->SetViewport(viewRect_);
     graphics_->SetColorWrite(true);
 }
@@ -1506,8 +1496,6 @@ void View::AllocateScreenBuffers()
     for (unsigned i = 0; i < neededBuffers; ++i)
         screenBuffers_.Push(renderer_->GetScreenBuffer(rtSize_.x_, rtSize_.y_, format, true));
     
-    screenBufferDepthStencil_ = neededBuffers ? GetDepthStencil(screenBuffers_[0]->GetRenderSurface()) : (RenderSurface*)0;
-    
     // Allocate extra render targets defined by the rendering path
     for (unsigned i = 0; i < renderPath_->renderTargets_.Size(); ++i)
     {
@@ -1546,7 +1534,7 @@ void View::AllocateScreenBuffers()
     }
 }
 
-void View::BlitFramebuffer(Texture2D* source, RenderSurface* destination, RenderSurface* depthStencil, bool depthWrite)
+void View::BlitFramebuffer(Texture2D* source, RenderSurface* destination, bool depthWrite)
 {
     PROFILE(BlitFramebuffer);
     
@@ -1559,7 +1547,7 @@ void View::BlitFramebuffer(Texture2D* source, RenderSurface* destination, Render
     graphics_->SetRenderTarget(0, destination);
     for (unsigned i = 1; i < MAX_RENDERTARGETS; ++i)
         graphics_->SetRenderTarget(i, (RenderSurface*)0);
-    graphics_->SetDepthStencil(depthStencil);
+    graphics_->SetDepthStencil(GetDepthStencil(destination));
     graphics_->SetViewport(viewRect_);
     
     String shaderName = "CopyFramebuffer";

+ 2 - 8
Engine/Graphics/View.h

@@ -152,7 +152,7 @@ private:
     /// Allocate needed screen buffers.
     void AllocateScreenBuffers();
     /// Blit the viewport from one surface to another.
-    void BlitFramebuffer(Texture2D* source, RenderSurface* destination, RenderSurface* depthStencil, bool depthWrite);
+    void BlitFramebuffer(Texture2D* source, RenderSurface* destination, bool depthWrite);
     /// Draw a fullscreen quad. Shaders and renderstates must have been set beforehand.
     void DrawFullscreenQuad(bool nearQuad);
     /// Query for occluders as seen from a camera.
@@ -197,7 +197,7 @@ private:
     void SetupLightVolumeBatch(Batch& batch);
     /// Render a shadow map.
     void RenderShadowMap(const LightBatchQueue& queue);
-    /// Return the proper depth-stencil surface to use for a rendertarget. Should only be called once per rendertarget.
+    /// Return the proper depth-stencil surface to use for a rendertarget.
     RenderSurface* GetDepthStencil(RenderSurface* renderTarget);
     
     /// Graphics subsystem.
@@ -220,14 +220,8 @@ private:
     OcclusionBuffer* occlusionBuffer_;
     /// Destination color rendertarget.
     RenderSurface* renderTarget_;
-    /// Destination depth stencil.
-    RenderSurface* depthStencil_;
-    /// Screenbuffers' depth stencil.
-    RenderSurface* screenBufferDepthStencil_;
     /// Effective color rendertarget to use, may be different if screenbuffers are used.
     RenderSurface* currentRenderTarget_;
-    /// Effective depth stencil to use, may be different if screenbuffers are used.
-    RenderSurface* currentDepthStencil_;
     /// Viewport rectangle.
     IntRect viewRect_;
     /// Viewport size.