Added clip transform matrix to the Graphics Controller 71/317871/6
authorDavid Steele <david.steele@samsung.com>
Thu, 19 Sep 2024 09:23:09 +0000 (10:23 +0100)
committerDavid Steele <david.steele@samsung.com>
Wed, 25 Sep 2024 17:32:34 +0000 (18:32 +0100)
For GL, this matrix should not be used, so doesn't affect
render time. For Vulkan, this will change to Vulkan
clip space, so adds another matrix multiply.

(Consider moving the projection matrix setup to graphics
controller...)

Moved the viewport/scissor setting to the secondary command buffer.
(It's not an issue for GL, but is for Vulkan)

Also ensured that the viewport near/far clip values are set.

Change-Id: I4c1842fad5766d9be769fe9dce79386f84b5459a

automated-tests/src/dali/dali-test-suite-utils/test-graphics-controller.cpp
automated-tests/src/dali/dali-test-suite-utils/test-graphics-controller.h
dali/graphics-api/graphics-controller.h
dali/graphics-api/graphics-types.h
dali/internal/render/common/render-algorithms.cpp
dali/internal/render/common/render-manager.cpp

index f0bc4d6d5dde5f659628ac54300d245fe7d59403..114879fb4faa9ec6e36cc41e6f9dba7419e38aef 100644 (file)
@@ -1505,4 +1505,22 @@ Graphics::UniquePtr<Graphics::Texture> TestGraphicsController::ReleaseTextureFro
   return texture;
 }
 
+bool TestGraphicsController::HasClipMatrix() const
+{
+  return true;
+}
+
+const Matrix& TestGraphicsController::GetClipMatrix() const
+{
+  // This matrix transforms from GL -> Vulkan clip space
+  constexpr float VULKAN_CLIP_MATRIX_DATA[] = {
+    1.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.5f, 0.0f, 0.0f, 0.0f, 0.5f, 1.0f};
+  static const Matrix VULKAN_CLIP_MATRIX(VULKAN_CLIP_MATRIX_DATA);
+  static const Matrix IDENTITY = Matrix::IDENTITY;
+
+  // For now, return IDENTITY to stay in GL clip space.
+  // @todo Add test toggle
+  return IDENTITY;
+}
+
 } // namespace Dali
index e21c30400f009814a08b0683288f1a7d6f5b05f3..2b0a9b97aaedb4ab9ee2facf08ba104f15b74ca6 100644 (file)
@@ -422,6 +422,9 @@ public: // ResourceId relative API.
    */
   Graphics::UniquePtr<Graphics::Texture> ReleaseTextureFromResourceId(uint32_t resourceId) override;
 
+  bool          HasClipMatrix() const override;
+  const Matrix& GetClipMatrix() const override;
+
 public: // Test Functions
   void SetAutoAttrCreation(bool v)
   {
@@ -499,14 +502,14 @@ public: // Test Functions
                                uint32_t                                      elementStrideInBytes)
   {
     TestGraphicsReflection::TestUniformInfo info;
-    info.name          = std::move(name);
-    info.type          = type;
-    info.uniformClass  = Graphics::UniformClass::UNIFORM;
-    info.numElements   = elementCount;
-    info.locations     = {0};
-    info.bufferIndex   = 0;                    // this will update when AddCustomUniformBlock called
-
-    auto retval= GetUniformBufferArrayStrideAndTypeSize(info, elementStrideInBytes);
+    info.name         = std::move(name);
+    info.type         = type;
+    info.uniformClass = Graphics::UniformClass::UNIFORM;
+    info.numElements  = elementCount;
+    info.locations    = {0};
+    info.bufferIndex  = 0; // this will update when AddCustomUniformBlock called
+
+    auto retval        = GetUniformBufferArrayStrideAndTypeSize(info, elementStrideInBytes);
     info.elementStride = std::max(retval.first, retval.second);
     info.offsets       = {blockInfo.size};
     blockInfo.size += (elementCount == 0 ? 1 : elementCount) * std::max(retval.first, retval.second);
@@ -567,4 +570,4 @@ public:
 
 } // namespace Dali
 
-#endif //TEST_GRAPHICS_CONTROLLER_H
+#endif // TEST_GRAPHICS_CONTROLLER_H
index 466edfa82fa30847c20f157cf56991af2211b056..19009339bf0e4772ac96f88d04560cebd7a89632 100644 (file)
@@ -412,6 +412,20 @@ public: // ResourceId relative API.
    */
   virtual UniquePtr<Graphics::Texture> ReleaseTextureFromResourceId(uint32_t resourceId) = 0;
 
+  /**
+   * @brief Determine if the backend needs to multiply the projection matrix by a clip matrix
+   *
+   * @return TRUE if the graphics backend requires an alternative clip matrix
+   */
+  virtual bool HasClipMatrix() const = 0;
+
+  /**
+   * @brief Get the alternative clipping matrix.
+   *
+   * @return the clipping matrix
+   */
+  virtual const Matrix& GetClipMatrix() const = 0;
+
 protected:
   /**
    * Creates controller
index 77800058bbd632acd52e179756e67b200815519d..dab4ab641eb3d9e560b06846e219f0a99c32bd08 100644 (file)
@@ -80,7 +80,7 @@ struct Viewport
   float width    = 0.0f;
   float height   = 0.0f;
   float minDepth = 0.0f;
-  float maxDepth = 0.0f;
+  float maxDepth = 1.0f;
 };
 
 /**
index fd56538e772b61a76df0737b171e0db5715fa446..7f067c17716aa28fd033ac4f22bb1c7b57294add 100644 (file)
@@ -40,6 +40,7 @@ namespace Render
 {
 namespace
 {
+
 struct GraphicsDepthCompareOp
 {
   constexpr explicit GraphicsDepthCompareOp(DepthFunction::Type compareOp)
@@ -147,7 +148,7 @@ struct GraphicsStencilOp
 
 inline Graphics::Viewport ViewportFromClippingBox(const Uint16Pair& sceneSize, ClippingBox clippingBox, int orientation)
 {
-  Graphics::Viewport viewport{static_cast<float>(clippingBox.x), static_cast<float>(clippingBox.y), static_cast<float>(clippingBox.width), static_cast<float>(clippingBox.height), 0.0f, 0.0f};
+  Graphics::Viewport viewport{static_cast<float>(clippingBox.x), static_cast<float>(clippingBox.y), static_cast<float>(clippingBox.width), static_cast<float>(clippingBox.height), 0.0f, 1.0f};
 
   if(orientation == 90 || orientation == 270)
   {
@@ -169,6 +170,8 @@ inline Graphics::Viewport ViewportFromClippingBox(const Uint16Pair& sceneSize, C
     viewport.x = sceneSize.GetX() - (clippingBox.x + clippingBox.width);
     viewport.y = sceneSize.GetY() - (clippingBox.y + clippingBox.height);
   }
+  viewport.minDepth = 0;
+  viewport.maxDepth = 1;
   return viewport;
 }
 
@@ -630,9 +633,9 @@ inline void RenderAlgorithms::ProcessRenderList(const RenderList&
 
   // Add root clipping rect (set manually for Render function by partial update for example)
   // on the bottom of the stack
+  Graphics::Viewport graphicsViewport = ViewportFromClippingBox(sceneSize, mViewportRectangle, 0);
   if(!rootClippingRect.IsEmpty())
   {
-    Graphics::Viewport graphicsViewport = ViewportFromClippingBox(sceneSize, mViewportRectangle, 0);
     secondaryCommandBuffer.SetScissorTestEnable(true);
     secondaryCommandBuffer.SetScissor(Rect2DFromRect(rootClippingRect, orientation, graphicsViewport));
     mScissorStack.push_back(rootClippingRect);
@@ -641,12 +644,13 @@ inline void RenderAlgorithms::ProcessRenderList(const RenderList&
   else if(!renderList.IsClipping())
   {
     secondaryCommandBuffer.SetScissorTestEnable(false);
+    //@todo Vk requires a scissor to be set, as we have turned on dynamic state scissor in the pipelines.
+    secondaryCommandBuffer.SetScissor(Rect2DFromClippingBox(mViewportRectangle, orientation, graphicsViewport));
     mScissorStack.push_back(mViewportRectangle);
   }
 
   if(renderList.IsClipping())
   {
-    Graphics::Viewport graphicsViewport = ViewportFromClippingBox(sceneSize, mViewportRectangle, 0);
     secondaryCommandBuffer.SetScissorTestEnable(true);
     const ClippingBox& layerScissorBox = renderList.GetClippingBox();
     secondaryCommandBuffer.SetScissor(Rect2DFromClippingBox(layerScissorBox, orientation, graphicsViewport));
@@ -657,6 +661,13 @@ inline void RenderAlgorithms::ProcessRenderList(const RenderList&
   // Prepare Render::Renderer Render for this secondary command buffer.
   Renderer::PrepareCommandBuffer();
 
+  // Modify by the clip matrix if necessary (transforms from GL clip space to alternative clip space)
+  Matrix clippedProjectionMatrix(projectionMatrix);
+  if(mGraphicsController.HasClipMatrix())
+  {
+    Matrix::Multiply(clippedProjectionMatrix, projectionMatrix, mGraphicsController.GetClipMatrix());
+  }
+
   // Loop through all RenderItems in the RenderList, set up any prerequisites to render them, then perform the render.
   for(uint32_t index = 0u; index < count; ++index)
   {
@@ -708,7 +719,7 @@ inline void RenderAlgorithms::ProcessRenderList(const RenderList&
         for(auto queue = 0u; queue < MAX_QUEUE; ++queue)
         {
           // Render the item. It will write into the command buffer everything it has to render
-          item.mRenderer->Render(secondaryCommandBuffer, bufferIndex, *item.mNode, item.mModelMatrix, item.mModelViewMatrix, viewMatrix, projectionMatrix, item.mScale, item.mSize, !item.mIsOpaque, instruction, renderTarget, queue);
+          item.mRenderer->Render(secondaryCommandBuffer, bufferIndex, *item.mNode, item.mModelMatrix, item.mModelViewMatrix, viewMatrix, clippedProjectionMatrix, item.mScale, item.mSize, !item.mIsOpaque, instruction, renderTarget, queue);
         }
       }
     }
index 5b32fd8028b29daed3ff47d973babaa798cde9fe..5aff37e3d7d8a9da0aeaa3edc483c56aca853293 100644 (file)
@@ -1257,10 +1257,7 @@ void RenderManager::RenderScene(Integration::RenderStatus& status, Integration::
       scissorArea,
       currentClearValues);
 
-    mainCommandBuffer->SetViewport({float(viewportRect.x),
-                                    float(viewportRect.y),
-                                    float(viewportRect.width),
-                                    float(viewportRect.height)});
+    // Note, don't set the viewport/scissor on the primary command buffer.
 
     mImpl->renderAlgorithms.ProcessRenderInstruction(
       instruction,
@@ -1288,7 +1285,8 @@ void RenderManager::RenderScene(Integration::RenderStatus& status, Integration::
 
   if(targetsToPresent.size() > 0u)
   {
-    DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_RENDER_FINISHED", [&](std::ostringstream& oss) { oss << "[" << targetsToPresent.size() << "]"; });
+    DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_RENDER_FINISHED", [&](std::ostringstream& oss)
+                                            { oss << "[" << targetsToPresent.size() << "]"; });
   }
 
   // Flush UBOs