Added test for UniformBlocks 70/294670/2
authorDavid Steele <david.steele@samsung.com>
Thu, 22 Jun 2023 17:57:26 +0000 (18:57 +0100)
committerDavid Steele <david.steele@samsung.com>
Fri, 23 Jun 2023 15:19:02 +0000 (16:19 +0100)
Test application shows uniform blocks in action in a custom shader,
and that properties can be used to write uniforms as normal.

Change-Id: Ibf6552084b491adf7fc6f05d5de0fe829ab5f58c
Signed-off-by: David Steele <david.steele@samsung.com>
com.samsung.dali-demo.xml
examples/uniform-blocks/README.md [new file with mode: 0644]
examples/uniform-blocks/shaders/uniform-block-alt.frag [new file with mode: 0644]
examples/uniform-blocks/shaders/uniform-block.frag [new file with mode: 0644]
examples/uniform-blocks/shaders/uniform-block.vert [new file with mode: 0644]
examples/uniform-blocks/uniform-blocks-example.cpp [new file with mode: 0644]
resources/po/en_GB.po
resources/po/en_US.po
shared/dali-demo-strings.h
tests-reel/dali-tests-reel.cpp

index 93194a1..67e34dd 100644 (file)
        <ui-application appid="transitions.example" exec="/usr/apps/com.samsung.dali-demo/bin/transitions.example" nodisplay="true" multiple="false" type="c++app" taskmanage="true">
                <label>Shadow button</label>
        </ui-application>
+       <ui-application appid="uniform-blocks.example" exec="/usr/apps/com.samsung.dali-demo/bin/uniform-blocks.example" nodisplay="true" multiple="false" type="c++app" taskmanage="true">
+               <label>Uniform Blocks</label>
+       </ui-application>
        <ui-application appid="video-view.example" exec="/usr/apps/com.samsung.dali-demo/bin/video-view.example" nodisplay="true" multiple="false" type="c++app" taskmanage="true">
                <label>Video View</label>
        </ui-application>
diff --git a/examples/uniform-blocks/README.md b/examples/uniform-blocks/README.md
new file mode 100644 (file)
index 0000000..96b133e
--- /dev/null
@@ -0,0 +1,22 @@
+This test is to validate the behaviour of UniformBlocks.
+
+It generates 200 actors with the same renderer. The frag shader
+has a 1k color table in a uniform block, with a color index property
+that is incremented for each actor that's created.
+
+On a 100ms timer, it removes the oldest actor and creates a new actor
+with the next color index.
+
+On first touch, it changes the shader, and subtracts the currently indexed
+color from the color in the vertex buffer.
+
+This shows that:
+    o Many uniform blocks are instantiated on a double-buffered UniformBuffer,
+    o Despite being a sparse shader, the full uniform block size is allocated,
+    o After touch, if everything is grey, then the color defined in the uniform
+      block is the same as the color defined in the vertex buffer.
+
+
+
+
+
diff --git a/examples/uniform-blocks/shaders/uniform-block-alt.frag b/examples/uniform-blocks/shaders/uniform-block-alt.frag
new file mode 100644 (file)
index 0000000..81cd3df
--- /dev/null
@@ -0,0 +1,12 @@
+layout(std140) uniform FragmentBlock
+{
+  lowp vec4 uColor;
+  mediump vec4 uColorArray[1024];
+  mediump int uColorIndex;
+};
+
+void main()
+{
+  // Test that the array color is the same as the actor color
+  fragColor = vec4(vec3(0.5, 0.5, 0.5) + vec3(uColorArray[uColorIndex].xyz-uColor.xyz)*0.5, 1.0);
+}
diff --git a/examples/uniform-blocks/shaders/uniform-block.frag b/examples/uniform-blocks/shaders/uniform-block.frag
new file mode 100644 (file)
index 0000000..9e699bf
--- /dev/null
@@ -0,0 +1,11 @@
+layout(std140) uniform FragmentBlock
+{
+  lowp vec4 uColor;
+  mediump vec4 uColorArray[1024];
+  mediump int uColorIndex;
+};
+
+void main()
+{
+  fragColor = uColorArray[uColorIndex];
+}
diff --git a/examples/uniform-blocks/shaders/uniform-block.vert b/examples/uniform-blocks/shaders/uniform-block.vert
new file mode 100644 (file)
index 0000000..cbf8ff9
--- /dev/null
@@ -0,0 +1,13 @@
+INPUT vec2 aPosition;
+
+layout(std140) uniform VertexBlock
+{
+  highp mat4 uMvpMatrix;
+  highp vec3 uSize;
+};
+
+void main()
+{
+  vec3 position = vec3(aPosition, 1.0) * uSize;
+  gl_Position = uMvpMatrix * vec4(position, 1);
+}
diff --git a/examples/uniform-blocks/uniform-blocks-example.cpp b/examples/uniform-blocks/uniform-blocks-example.cpp
new file mode 100644 (file)
index 0000000..30853b9
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali-toolkit/dali-toolkit.h>
+
+#include "generated/uniform-block-vert.h"
+#include "generated/uniform-block-frag.h"
+#include "generated/uniform-block-alt-frag.h"
+
+using namespace Dali;
+using Dali::Toolkit::TextLabel;
+
+
+
+/**
+ * This application tests that shaders with uniform blocks work as expected.
+ */
+class UniformBlocksController : public ConnectionTracker
+{
+public:
+  UniformBlocksController(Application& application)
+  : mApplication(application)
+  {
+    // Connect to the Application's Init signal
+    mApplication.InitSignal().Connect(this, &UniformBlocksController::Create);
+  }
+
+  ~UniformBlocksController() = default; // Nothing to do in destructor
+
+  // The Init signal is received once (only) during the Application lifetime
+  void Create(Application& application)
+  {
+    // Get a handle to the window
+    Window window = application.GetWindow();
+    window.SetBackgroundColor(Color::WHITE);
+
+    CreateShader(0);
+    CreateGeometry();
+    CreateRenderer();
+    mFirstActor = window.GetRootLayer().GetChildCount();
+
+    for(int i=0; i<200; ++i)
+    {
+      AddActor(i);
+    }
+
+    // Respond to a touch anywhere on the window
+    window.GetRootLayer().TouchedSignal().Connect(this, &UniformBlocksController::OnTouch);
+
+    // Respond to key events
+    window.KeyEventSignal().Connect(this, &UniformBlocksController::OnKeyEvent);
+    mTimer = Timer::New(100);
+    mTimer.TickSignal().Connect(this, &UniformBlocksController::OnTick);
+    mTimer.Start();
+  }
+
+  bool OnTick()
+  {
+    static int index=200;
+    Window window = mApplication.GetWindow();
+    Layer layer = window.GetRootLayer();
+    Actor child = layer.GetChildAt(mFirstActor);
+    UnparentAndReset(child);
+    AddActor(index);
+    index = (index+1)%1024;
+    return true;
+  }
+
+  bool OnTouch(Actor actor, const TouchEvent& touch)
+  {
+    static int testNumber=0;
+    if(touch.GetState(0) == PointState::STARTED)
+    {
+      testNumber++;
+      if(testNumber >=2)
+        mApplication.Quit();
+
+      CreateShader(testNumber);
+      mRenderer = Renderer::New(mGeometry, mShader);
+
+      Actor parent = mApplication.GetWindow().GetRootLayer();
+      for(uint32_t i=0; i<parent.GetChildCount(); ++i)
+      {
+        parent.GetChildAt(i).RemoveRenderer(0);
+        parent.GetChildAt(i).AddRenderer(mRenderer);
+      }
+    }
+    return true;
+  }
+
+  void OnKeyEvent(const KeyEvent& event)
+  {
+    if(event.GetState() == KeyEvent::DOWN)
+    {
+      if(IsKey(event, Dali::DALI_KEY_ESCAPE) || IsKey(event, Dali::DALI_KEY_BACK))
+      {
+        mApplication.Quit();
+      }
+    }
+  }
+
+  void AddActor(int n)
+  {
+    Actor actor = Actor::New();
+    actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+    actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+    actor.SetProperty(Actor::Property::POSITION, Vector3(Random::Range(-200.0f, 200.0f), Random::Range(-300.0f, 300.0f), 0.0f));;
+    actor.SetProperty( Actor::Property::SIZE, Vector2(32, 32) );
+    Vector4 color(Random::Range(0.1f,1.0f),Random::Range(0.1f,1.0f),Random::Range(0.1f,1.0f),1.0f);
+    actor.SetProperty( Actor::Property::COLOR, color);
+
+    actor.AddRenderer(mRenderer);
+
+    actor.RegisterProperty("uColorIndex", n);
+    char buffer[80];
+    sprintf(buffer, "uColorArray[%d]", n);
+    actor.RegisterProperty(buffer, color);
+
+    Window window = mApplication.GetWindow();
+    window.Add(actor);
+  }
+
+  void CreateShader(int testNumber)
+  {
+
+
+    // Create shaders
+    switch(testNumber)
+    {
+      case 0:
+      {
+        mShader = Shader::New(Dali::Shader::GetVertexShaderPrefix() + std::string(SHADER_UNIFORM_BLOCK_VERT),
+                              Dali::Shader::GetFragmentShaderPrefix() + std::string(SHADER_UNIFORM_BLOCK_FRAG));
+        break;
+      }
+      case 1:
+      {
+        mShader = Shader::New(Dali::Shader::GetVertexShaderPrefix() + std::string(SHADER_UNIFORM_BLOCK_VERT),
+                              Dali::Shader::GetFragmentShaderPrefix() + std::string(SHADER_UNIFORM_BLOCK_ALT_FRAG));
+        break;
+      }
+    }
+  }
+
+  void CreateGeometry()
+  {
+    struct Vertex2D
+    {
+      Vertex2D(const Vector2& _co) :
+        co(_co){}
+      Dali::Vector2 co{};
+    };
+    const static Vector2 C(0.5f, 0.5f);
+    struct Quad2D
+    {
+      Vertex2D a0{Vector2(0.0f, 0.0f)-C};
+      Vertex2D a1{Vector2(1.0f, 0.0f)-C};
+      Vertex2D a2{Vector2(1.0f, 1.0f)-C};
+      Vertex2D a3{Vector2(0.0f, 0.0f)-C};
+      Vertex2D a4{Vector2(1.0f, 1.0f)-C};
+      Vertex2D a5{Vector2(0.0f, 1.0f)-C};
+    } QUAD;
+
+    // Create geometry
+    Geometry geometry = Geometry::New();
+
+    Property::Map attrMap{};
+    attrMap.Add("aPosition", Property::Type::VECTOR2);
+    VertexBuffer vb = VertexBuffer::New(attrMap);
+    vb.SetData( &QUAD, 6 );
+
+    geometry.SetType( Geometry::Type::TRIANGLES);
+    geometry.AddVertexBuffer(vb);
+    mGeometry = geometry;
+  }
+
+  void CreateRenderer()
+  {
+    mRenderer = Renderer::New( mGeometry, mShader);
+  }
+
+private:
+  Application& mApplication;
+
+  Shader mShader;
+  Geometry mGeometry;
+  Renderer mRenderer;
+  uint32_t mFirstActor;
+  Timer mTimer;
+};
+
+int DALI_EXPORT_API main(int argc, char** argv)
+{
+  Application          application = Application::New(&argc, &argv);
+  UniformBlocksController test(application);
+  application.MainLoop();
+  return 0;
+}
index 3d40350..0628911 100755 (executable)
@@ -324,3 +324,6 @@ msgstr "Web View"
 
 msgid "DALI_DEMO_STR_TITLE_ANIMATED_VECTOR_IMAGES"
 msgstr "Animated Vector Images"
+
+msgid "DALI_DEMO_STR_TITLE_UNIFORM_BLOCKS"
+msgstr "Uniform Blocks"
index 0812a69..94d60d7 100755 (executable)
@@ -342,3 +342,6 @@ msgstr "Text Bitmap Font"
 
 msgid "DALI_DEMO_STR_TITLE_WAVES"
 msgstr "Waves"
+
+msgid "DALI_DEMO_STR_TITLE_UNIFORM_BLOCKS"
+msgstr "Uniform Blocks"
index b914a3f..0e2dc10 100644 (file)
@@ -148,6 +148,7 @@ extern "C"
 #define DALI_DEMO_STR_TITLE_TEXT_RENDERER dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_TEXT_RENDERER")
 #define DALI_DEMO_STR_TITLE_TEXT_VISUAL dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_TEXT_VISUAL")
 #define DALI_DEMO_STR_TITLE_TEXT_LABEL_BITMAP_FONT dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_TEXT_LABEL_BITMAP_FONT")
+#define DALI_DEMO_STR_TITLE_UNIFORM_BLOCKS dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_UNIFORM_BLOCKS")
 
 #else // !INTERNATIONALIZATION_ENABLED
 
@@ -265,6 +266,7 @@ extern "C"
 #define DALI_DEMO_STR_TITLE_TEXT_RENDERER "Text Renderer"
 #define DALI_DEMO_STR_TITLE_TEXT_VISUAL "Text Visual"
 #define DALI_DEMO_STR_TITLE_TEXT_LABEL_BITMAP_FONT "Text Bitmap Font"
+#define DALI_DEMO_STR_TITLE_UNIFORM_BLOCKS "Uniform Blocks"
 #endif
 
 #ifdef __cplusplus
index fd5d680..8dfd6ff 100644 (file)
@@ -59,6 +59,7 @@ int DALI_EXPORT_API main(int argc, char** argv)
   demo.AddExample(Example("simple-text-renderer.example", DALI_DEMO_STR_TITLE_TEXT_RENDERER));
   demo.AddExample(Example("simple-text-visual.example", DALI_DEMO_STR_TITLE_TEXT_VISUAL));
   demo.AddExample(Example("simple-bitmap-font-text-label.example", DALI_DEMO_STR_TITLE_TEXT_LABEL_BITMAP_FONT));
+  demo.AddExample(Example("uniform-blocks.example", DALI_DEMO_STR_TITLE_UNIFORM_BLOCKS));
 
   demo.SortAlphabetically(true);