Browse Source

Fix the Depth shader on D3D11. Simplify View code to determine whether a substitute RT for the backbuffer is needed. Fix having to render the hardware depth stencil twice in the ForwardDepth renderpath.

Lasse Öörni 10 years ago
parent
commit
6f8ed55c0a

+ 1 - 1
Docs/Reference.dox

@@ -1259,7 +1259,7 @@ An example render path for readable hardware depth exists in bin/CoreData/Render
 
 The render path starts by allocating a readable depth-stencil texture the same size as the destination viewport, clearing its depth, then rendering a depth-only pass to it. Next the destination color rendertarget is cleared normally, while the readable depth texture is used as the depth-stencil for that and all subsequent commands. Any command after the depth render pass could now bind the depth texture to an unit for sampling, for example for smooth particle or SSAO effects.
 
-The ForwardDepth.xml render path does the same, but using a linear depth rendertarget instead of a hardware depth texture. The advantage is better compatibility (guaranteed to work without checking \ref Graphics::GetReadableDepthSupport "GetReadableDepthSupport()") but it has worse performance as it will fill the hardware depth-stencil twice.
+The ForwardDepth.xml render path does the same, but using a linear depth rendertarget instead of a hardware depth texture. The advantage is better compatibility (guaranteed to work without checking \ref Graphics::GetReadableDepthSupport "GetReadableDepthSupport()") but it has worse performance as it will perform an additional full scene rendering pass.
 
 \section RenderPaths_ForwardLighting Forward lighting special considerations
 

+ 35 - 59
Source/Urho3D/Graphics/View.cpp

@@ -1854,33 +1854,50 @@ bool View::CheckPingpong(unsigned index)
 
 void View::AllocateScreenBuffers()
 {
+    bool hasScenePassToRTs = false;
+    bool hasCustomDepth = false;
+    bool hasViewportRead = false;
+    bool hasPingpong = false;
     bool needSubstitute = false;
     unsigned numViewportTextures = 0;
     depthOnlyDummyTexture_ = 0;
 
-#ifdef URHO3D_OPENGL
-    // Due to FBO limitations, in OpenGL deferred modes need to render to texture first and then blit to the backbuffer
-    // Also, if rendering to a texture with full deferred rendering, it must be RGBA to comply with the rest of the buffers,
-    // unless using OpenGL 3
-    if ((deferred_ && !renderTarget_) || (!Graphics::GetGL3Support() && deferredAmbient_ && renderTarget_ &&
-                                          renderTarget_->GetParentTexture()->GetFormat() != Graphics::GetRGBAFormat()))
-        needSubstitute = true;
-    // Also need substitute if rendering to backbuffer using a custom (readable) depth buffer
-    if (!renderTarget_ && !needSubstitute)
+    // Check for commands with special meaning: has custom depth, renders a scene pass to other than the destination viewport,
+    // read the viewport, or pingpong between viewport textures. These may trigger the need to substitute the destination RT
+    for (unsigned i = 0; i < renderPath_->commands_.Size(); ++i)
     {
-        for (unsigned i = 0; i < renderPath_->commands_.Size(); ++i)
+        const RenderPathCommand& command = renderPath_->commands_[i];
+        if (!IsNecessary(command))
+            continue;
+        if (!hasViewportRead && CheckViewportRead(command))
+            hasViewportRead = true;
+        if (!hasPingpong && CheckPingpong(i))
+            hasPingpong = true;
+        if (command.depthStencilName_.Length())
+            hasCustomDepth = true;
+        if (!hasScenePassToRTs && command.type_ == CMD_SCENEPASS)
         {
-            const RenderPathCommand& command = renderPath_->commands_[i];
-            if (!IsNecessary(command))
-                continue;
-            if (command.depthStencilName_.Length() && command.outputs_.Size() && !command.outputs_[0].first_.Compare("viewport",
-                false))
+            for (unsigned j = 0; j < command.outputs_.Size(); ++j)
             {
-                needSubstitute = true;
-                break;
+                if (command.outputs_[j].first_.Compare("viewport", false))
+                {
+                    hasScenePassToRTs = true;
+                    break;
+                }
             }
         }
     }
+
+#ifdef URHO3D_OPENGL
+    // Due to FBO limitations, in OpenGL deferred modes need to render to texture first and then blit to the backbuffer
+    // Also, if rendering to a texture with full deferred rendering, it must be RGBA to comply with the rest of the buffers,
+    // unless using OpenGL 3
+    if (((deferred_ || hasScenePassToRTs) && !renderTarget_) || (!Graphics::GetGL3Support() && deferredAmbient_ && renderTarget_ 
+        && renderTarget_->GetParentTexture()->GetFormat() != Graphics::GetRGBAFormat()))
+            needSubstitute = true;
+    // Also need substitute if rendering to backbuffer using a custom (readable) depth buffer
+    if (!renderTarget_ && hasCustomDepth)
+        needSubstitute = true;
 #endif
     // If backbuffer is antialiased when using deferred rendering, need to reserve a buffer
     if (deferred_ && !renderTarget_ && graphics_->GetMultiSample() > 1)
@@ -1889,34 +1906,8 @@ void View::AllocateScreenBuffers()
     // textures will be sized equal to the viewport
     if (viewSize_.x_ < rtSize_.x_ || viewSize_.y_ < rtSize_.y_)
     {
-        if (deferred_)
+        if (deferred_ || hasScenePassToRTs || hasCustomDepth)
             needSubstitute = true;
-        else if (!needSubstitute)
-        {
-            // Check also if using MRT without deferred rendering and rendering to the viewport and another texture,
-            // or using custom depth
-            for (unsigned i = 0; i < renderPath_->commands_.Size(); ++i)
-            {
-                const RenderPathCommand& command = renderPath_->commands_[i];
-                if (!IsNecessary(command))
-                    continue;
-                if (command.depthStencilName_.Length())
-                    needSubstitute = true;
-                if (!needSubstitute && command.outputs_.Size() > 1)
-                {
-                    for (unsigned j = 0; j < command.outputs_.Size(); ++j)
-                    {
-                        if (!command.outputs_[j].first_.Compare("viewport", false))
-                        {
-                            needSubstitute = true;
-                            break;
-                        }
-                    }
-                }
-                if (needSubstitute)
-                    break;
-            }
-        }
     }
 
     // Follow final rendertarget format, or use RGB to match the backbuffer format
@@ -1935,21 +1926,6 @@ void View::AllocateScreenBuffers()
         format = Graphics::GetRGBAFormat();
 #endif
 
-    // Check for commands which read the viewport, or pingpong between viewport textures
-    bool hasViewportRead = false;
-    bool hasPingpong = false;
-
-    for (unsigned i = 0; i < renderPath_->commands_.Size(); ++i)
-    {
-        const RenderPathCommand& command = renderPath_->commands_[i];
-        if (!IsNecessary(command))
-            continue;
-        if (CheckViewportRead(command))
-            hasViewportRead = true;
-        if (!hasPingpong && CheckPingpong(i))
-            hasPingpong = true;
-    }
-
     if (hasViewportRead)
     {
         ++numViewportTextures;

+ 2 - 2
bin/CoreData/RenderPaths/ForwardDepth.xml

@@ -1,8 +1,8 @@
 <renderpath>
     <rendertarget name="depth" sizedivisor="1 1" format="lineardepth" />
-    <command type="clear" color="1 1 1 1" depth="1.0" output="depth" />
+    <command type="clear" color="1 1 1 1" depth="1.0" stencil="0" output="depth" />
     <command type="scenepass" pass="depth" output="depth" />
-    <command type="clear" color="fog" depth="1.0" stencil="0" />
+    <command type="clear" color="fog" />
     <command type="scenepass" pass="base" vertexlights="true" metadata="base" />
     <command type="forwardlights" pass="light" />
     <command type="scenepass" pass="postopaque" />

+ 3 - 3
bin/CoreData/Shaders/HLSL/Depth.hlsl

@@ -12,7 +12,7 @@ void VS(float4 iPos : POSITION,
     #endif
     float2 iTexCoord : TEXCOORD0,
     out float3 oTexCoord : TEXCOORD0,
-    out float4 oPos : POSITION)
+    out float4 oPos : OUTPOSITION)
 {
     float4x3 modelMatrix = iModelMatrix;
     float3 worldPos = GetWorldPos(modelMatrix);
@@ -22,10 +22,10 @@ void VS(float4 iPos : POSITION,
 
 void PS(
     float3 iTexCoord : TEXCOORD0,
-    out float4 oColor : COLOR0)
+    out float4 oColor : OUTCOLOR0)
 {
     #ifdef ALPHAMASK
-        float alpha = tex2D(sDiffMap, iTexCoord.xy).a;
+        float alpha = Sample2D(sDiffMap, iTexCoord.xy).a;
         if (alpha < 0.5)
             discard;
     #endif