Vulkan backend initialisation
authoradam.b <jsr184@gmail.com>
Thu, 25 May 2017 16:16:35 +0000 (17:16 +0100)
committeradam.b <jsr184@gmail.com>
Mon, 5 Jun 2017 10:37:32 +0000 (11:37 +0100)
Instance, device, surface and swapchain work.

Change-Id: I7a3816a885761072c9b42c7acc925a79f337d130

45 files changed:
dali/graphics/file.list
dali/graphics/graphics-logical-device.cpp [new file with mode: 0644]
dali/graphics/graphics-logical-device.h [new file with mode: 0644]
dali/graphics/graphics-physical-device.cpp [new file with mode: 0644]
dali/graphics/graphics-physical-device.h [new file with mode: 0644]
dali/graphics/graphics-surface.cpp [new file with mode: 0644]
dali/graphics/graphics-surface.h [new file with mode: 0644]
dali/graphics/graphics-swapchain.cpp [new file with mode: 0644]
dali/graphics/graphics-swapchain.h [new file with mode: 0644]
dali/graphics/integration/graphics-logical-device-base.h [new file with mode: 0644]
dali/graphics/integration/graphics-physical-device-base.h [new file with mode: 0644]
dali/graphics/integration/graphics-surface-base.h [new file with mode: 0644]
dali/graphics/integration/graphics-swapchain-base.h [new file with mode: 0644]
dali/graphics/vulkan-api-test.cpp [new file with mode: 0644]
dali/graphics/vulkan/buffer.cpp [new file with mode: 0644]
dali/graphics/vulkan/buffer.h [new file with mode: 0644]
dali/graphics/vulkan/command-buffer.cpp [new file with mode: 0644]
dali/graphics/vulkan/command-buffer.h [new file with mode: 0644]
dali/graphics/vulkan/command-pool.cpp [new file with mode: 0644]
dali/graphics/vulkan/command-pool.h [new file with mode: 0644]
dali/graphics/vulkan/command-queue.cpp [new file with mode: 0644]
dali/graphics/vulkan/command-queue.h [new file with mode: 0644]
dali/graphics/vulkan/common.h [new file with mode: 0644]
dali/graphics/vulkan/device-memory.cpp [new file with mode: 0644]
dali/graphics/vulkan/device-memory.h [new file with mode: 0644]
dali/graphics/vulkan/frame-stack.h [new file with mode: 0644]
dali/graphics/vulkan/framebuffer.cpp [new file with mode: 0644]
dali/graphics/vulkan/framebuffer.h [new file with mode: 0644]
dali/graphics/vulkan/image-view.cpp [new file with mode: 0644]
dali/graphics/vulkan/image-view.h [new file with mode: 0644]
dali/graphics/vulkan/image.cpp [new file with mode: 0644]
dali/graphics/vulkan/image.h [new file with mode: 0644]
dali/graphics/vulkan/logical-device.cpp [new file with mode: 0644]
dali/graphics/vulkan/logical-device.h [new file with mode: 0644]
dali/graphics/vulkan/physical-device.cpp [new file with mode: 0644]
dali/graphics/vulkan/physical-device.h [new file with mode: 0644]
dali/graphics/vulkan/surface.cpp [new file with mode: 0644]
dali/graphics/vulkan/surface.h [new file with mode: 0644]
dali/graphics/vulkan/surface/vulkan-surface-base.h [new file with mode: 0644]
dali/graphics/vulkan/surface/xcb-surface.cpp [new file with mode: 0644]
dali/graphics/vulkan/surface/xcb-surface.h [new file with mode: 0644]
dali/graphics/vulkan/surface/xlib-surface.cpp [new file with mode: 0644]
dali/graphics/vulkan/surface/xlib-surface.h [new file with mode: 0644]
dali/graphics/vulkan/swapchain.cpp [new file with mode: 0644]
dali/graphics/vulkan/swapchain.h [new file with mode: 0644]

index 666ef14..1692e26 100644 (file)
@@ -1,4 +1,22 @@
 # Add graphics source files here
 
 graphics_src_files = \
-  $(graphics_src_dir)/graphics-controller.cpp
+  $(graphics_src_dir)/graphics-controller.cpp \
+    $(graphics_src_dir)/graphics-controller.cpp \
+    $(graphics_src_dir)/graphics-logical-device.cpp \
+    $(graphics_src_dir)/graphics-physical-device.cpp \
+    $(graphics_src_dir)/graphics-surface.cpp \
+    $(graphics_src_dir)/graphics-swapchain.cpp \
+    $(graphics_src_dir)/vulkan/image.cpp \
+    $(graphics_src_dir)/vulkan/device-memory.cpp \
+    $(graphics_src_dir)/vulkan/command-queue.cpp \
+    $(graphics_src_dir)/vulkan/surface.cpp \
+    $(graphics_src_dir)/vulkan/logical-device.cpp \
+    $(graphics_src_dir)/vulkan/command-buffer.cpp \
+    $(graphics_src_dir)/vulkan/image-view.cpp \
+    $(graphics_src_dir)/vulkan/command-pool.cpp \
+    $(graphics_src_dir)/vulkan/framebuffer.cpp \
+    $(graphics_src_dir)/vulkan/physical-device.cpp \
+    $(graphics_src_dir)/vulkan/swapchain.cpp \
+    $(graphics_src_dir)/vulkan/buffer.cpp
+
diff --git a/dali/graphics/graphics-logical-device.cpp b/dali/graphics/graphics-logical-device.cpp
new file mode 100644 (file)
index 0000000..fa7f694
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2017 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/graphics/graphics-logical-device.h>
+
+namespace Dali
+{
+namespace Graphics
+{
+
+GraphicsSwapchain GraphicsLogicalDevice::CreateSwapchain(const GraphicsSurface& surface,
+                                                         uint32_t               bufferCount,
+                                                         DepthStencil           depthStencil,
+                                                         VSyncMode              enforceVSync)
+{
+  return GetObject()->CreateSwapchain(surface, bufferCount, depthStencil, enforceVSync);
+}
+}
+}
diff --git a/dali/graphics/graphics-logical-device.h b/dali/graphics/graphics-logical-device.h
new file mode 100644 (file)
index 0000000..c28c696
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef DALI_CORE_GRAPHICS_GRAPHICS_LOGICAL_DEVICE_H
+#define DALI_CORE_GRAPHICS_GRAPHICS_LOGICAL_DEVICE_H
+
+/*
+ * Copyright (c) 2017 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/graphics/graphics-swapchain.h>
+#include <dali/graphics/integration/graphics-logical-device-base.h>
+
+namespace Dali
+{
+namespace Graphics
+{
+
+using GraphicsLogicalDeviceHandle = VkHandleBase< GraphicsLogicalDeviceBase >;
+
+class GraphicsLogicalDevice : public GraphicsLogicalDeviceHandle
+{
+public:
+  GraphicsLogicalDevice(GraphicsLogicalDeviceBase* impl = nullptr)
+  : GraphicsLogicalDeviceHandle{impl}
+  {
+  }
+
+  using GraphicsLogicalDeviceHandle::operator=;
+
+  GraphicsSwapchain CreateSwapchain(const GraphicsSurface& surface,
+                                    uint32_t               bufferCount,
+                                    DepthStencil           depthStencil,
+                                    VSyncMode              enforceVSync);
+};
+
+} // Graphics
+} // Dali
+
+#endif //DALI_CORE_GRAPHICS_GRAPHICS_LOGICAL_DEVICE_H
diff --git a/dali/graphics/graphics-physical-device.cpp b/dali/graphics/graphics-physical-device.cpp
new file mode 100644 (file)
index 0000000..055c2cf
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2017 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/graphics/graphics-physical-device.h>
+
+namespace Dali
+{
+namespace Graphics
+{
+
+GraphicsPhysicalDevice GraphicsPhysicalDevice::New()
+{
+  return GraphicsPhysicalDevice(nullptr);
+}
+
+bool GraphicsPhysicalDevice::Initialise(const ExtensionNameList& extensions, const ValidationLayerFlags2& layers)
+{
+  return GetObject()->Initialise(extensions, layers);
+}
+
+bool GraphicsPhysicalDevice::IsExtensionAvailable(const std::string& instanceExtensionName) const
+{
+  return GetObject()->IsExtensionAvailable(instanceExtensionName);
+}
+
+bool GraphicsPhysicalDevice::IsLayerAvailable(const std::string& instanceLayerName) const
+{
+  return GetObject()->IsLayerAvailable(instanceLayerName);
+}
+
+bool GraphicsPhysicalDevice::ChoosePhysicalDevice(const PhysicalDeviceFlags& flags)
+{
+  return GetObject()->ChoosePhysicalDevice(flags);
+}
+
+GraphicsLogicalDevice GraphicsPhysicalDevice::CreateLogicalDevice(const ExtensionNameList& enabledExtensions)
+{
+  return GetObject()->CreateLogicalDevice(enabledExtensions);
+}
+
+GraphicsLogicalDevice GraphicsPhysicalDevice::CreateLogicalDevice()
+{
+  return CreateLogicalDevice(ExtensionNameList());
+}
+
+GraphicsSurface GraphicsPhysicalDevice::CreateSurface(const NativeSurfaceCreateInfo& info)
+{
+  return GetObject()->CreateSurface(info);
+}
+
+} // Graphics
+} // Dali
\ No newline at end of file
diff --git a/dali/graphics/graphics-physical-device.h b/dali/graphics/graphics-physical-device.h
new file mode 100644 (file)
index 0000000..95e207d
--- /dev/null
@@ -0,0 +1,104 @@
+#ifndef DALI_CORE_GRAPHICS_PHYSICAL_DEVICE_H
+#define DALI_CORE_GRAPHICS_PHYSICAL_DEVICE_H
+
+/*
+ * Copyright (c) 2017 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/graphics/graphics-logical-device.h>
+#include <dali/graphics/graphics-surface.h>
+#include <dali/graphics/integration/graphics-physical-device-base.h>
+#include <dali/graphics/vulkan/common.h>
+
+namespace Dali
+{
+namespace Graphics
+{
+
+class GraphicsPhysicalDevice : public VkHandleBase< Integration::GraphicsPhysicalDeviceBase >
+{
+public:
+  GraphicsPhysicalDevice(Integration::GraphicsPhysicalDeviceBase* impl = nullptr)
+  : VkHandleBase{impl}
+  {
+  }
+
+  using VkHandleBase::operator=;
+
+public:
+  /**
+   * Creates new uninitialised physical device
+   * @return
+   */
+  static GraphicsPhysicalDevice New();
+
+  /**
+   *
+   * @param extensions
+   * @param layers
+   * @return
+   */
+  bool Initialise(const ExtensionNameList& extensions, const ValidationLayerFlags2& layers);
+
+  /**
+   *
+   * @param instanceExtensionName
+   * @return
+   */
+  bool IsExtensionAvailable(const std::string& instanceExtensionName) const;
+
+  /**
+   *
+   * @param instanceExtensionName
+   * @return
+   */
+  bool IsLayerAvailable(const std::string& instanceExtensionName) const;
+
+  /**
+ *
+ * @param flags
+ * @return
+ */
+  bool ChoosePhysicalDevice(const PhysicalDeviceFlags& flags = 0u);
+
+  /**
+   * Creates logical device from the physical device
+   * @param enabledExtensions
+   * @return
+   */
+  GraphicsLogicalDevice CreateLogicalDevice(const ExtensionNameList& enabledExtensions);
+
+  /**
+   *
+   * @return
+   */
+  GraphicsLogicalDevice CreateLogicalDevice();
+
+  // temporary solution to bind physical device with surface
+  /**
+   *
+   * @param info
+   * @return
+   */
+  GraphicsSurface CreateSurface(const NativeSurfaceCreateInfo& info);
+};
+
+using PhysicalDeviceHandle = VkHandleBase< Integration::GraphicsPhysicalDeviceBase >;
+
+} // Graphics
+} // Dali
+
+#endif //DALI_CORE_GRAPHICSPHYSICALDEVICE_H
diff --git a/dali/graphics/graphics-surface.cpp b/dali/graphics/graphics-surface.cpp
new file mode 100644 (file)
index 0000000..8512d54
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2017 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/graphics/graphics-surface.h>
+#include <dali/graphics/integration/graphics-surface-base.h>
+
+namespace Dali
+{
+namespace Graphics
+{
+bool GraphicsSurface::Initialise()
+{
+  return GetObject()->Initialise();
+}
+
+bool GraphicsSurface::Replace()
+{
+  return GetObject()->Replace();
+}
+
+bool GraphicsSurface::Destroy()
+{
+  return GetObject()->Destroy();
+}
+
+uint32_t GraphicsSurface::GetWidth()
+{
+  return GetObject()->GetWidth();
+}
+
+uint32_t GraphicsSurface::GetHeight()
+{
+  return GetObject()->GetHeight();
+}
+
+}
+}
\ No newline at end of file
diff --git a/dali/graphics/graphics-surface.h b/dali/graphics/graphics-surface.h
new file mode 100644 (file)
index 0000000..469dd5e
--- /dev/null
@@ -0,0 +1,80 @@
+#ifndef DALI_CORE_GRAPHICS_SURFACE_H
+#define DALI_CORE_GRAPHICS_SURFACE_H
+
+/*
+ * Copyright (c) 2017 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/graphics/integration/graphics-surface-base.h>
+#include <dali/graphics/vulkan/common.h>
+
+namespace Dali
+{
+namespace Graphics
+{
+class GraphicsPhysicalDevice;
+
+enum class NativeSurfaceType
+{
+  UNDEFINED,
+  X11,
+  XCB,
+  WAYLAND,
+  ANDROID_NATIVE_WINDOW,
+  WIN32
+};
+
+struct NativeSurfaceCreateInfo
+{
+  NativeSurfaceCreateInfo(NativeSurfaceType type) : surfaceType{type}
+  {
+  }
+  NativeSurfaceType surfaceType;
+};
+
+using SurfaceHandle = VkHandleBase< Integration::GraphicsSurfaceBase >;
+
+class GraphicsSurface : public SurfaceHandle
+{
+public:
+  GraphicsSurface(Integration::GraphicsSurfaceBase* impl = nullptr) : SurfaceHandle{impl}
+  {
+  }
+  using SurfaceHandle::operator=;
+
+  template< typename T, typename... ARGS >
+  static GraphicsSurface New(const GraphicsPhysicalDevice& physicalDevice, ARGS&&... args)
+  {
+    GraphicsSurface retval = (new T(physicalDevice, args...));
+    if(!retval.Initialise())
+    {
+      retval = nullptr;
+    }
+    return retval;
+  }
+
+  bool     Initialise();
+  bool     Replace();
+  bool     Destroy();
+  uint32_t GetWidth();
+  uint32_t GetHeight();
+
+private:
+};
+}
+}
+
+#endif //DALI_CORE_GRRAPHICSSURFACE_H
diff --git a/dali/graphics/graphics-swapchain.cpp b/dali/graphics/graphics-swapchain.cpp
new file mode 100644 (file)
index 0000000..f7110fa
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2017 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 "graphics-swapchain.h"
+
+#include <dali/graphics/integration/graphics-swapchain-base.h>
+
+namespace Dali
+{
+namespace Graphics
+{
+
+namespace
+{
+Integration::GraphicsSwapchainBase* GetImpl(SwapchainHandle* handle)
+{
+  return handle->GetObject();
+}
+}
+
+void GraphicsSwapchain::Initialise()
+{
+  GetImpl(this)->Initialise();
+}
+
+/**
+ * Acquires next renderable frame from swapchain
+ */
+void GraphicsSwapchain::AcquireFrame()
+{
+  GetImpl(this)->AcquireFrame();
+}
+
+/**
+ * Presents frame
+ */
+void GraphicsSwapchain::PresentFrame()
+{
+  GetImpl(this)->PresentFrame();
+}
+}
+}
\ No newline at end of file
diff --git a/dali/graphics/graphics-swapchain.h b/dali/graphics/graphics-swapchain.h
new file mode 100644 (file)
index 0000000..1421182
--- /dev/null
@@ -0,0 +1,83 @@
+#ifndef DALI_CORE_GRAPHICS_SWAPCHAIN_H
+#define DALI_CORE_GRAPHICS_SWAPCHAIN_H
+
+/*
+ * Copyright (c) 2017 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/graphics/integration/graphics-swapchain-base.h>
+#include <dali/graphics/vulkan/common.h>
+
+#include <cinttypes>
+
+namespace Dali
+{
+namespace Graphics
+{
+class GraphicsPhysicalDevice;
+
+/**
+ * DepthStencil enum values
+ */
+enum class DepthStencil
+{
+  NONE,
+  DEPTH_16,
+  DEPTH_24,
+  DEPTH_16_STENCIL_8,
+  DEPTH_24_STENCIL_8
+};
+
+/**
+ * Vsync mode values
+ */
+enum class VSyncMode
+{
+  DISABLED = 0,
+  ENABLED = 1
+};
+
+class GraphicsContext;
+
+using SwapchainHandle = VkHandleBase< Integration::GraphicsSwapchainBase >;
+
+class GraphicsSwapchain : public SwapchainHandle
+{
+public:
+
+  GraphicsSwapchain(Integration::GraphicsSwapchainBase* o = nullptr) : SwapchainHandle{o} {};
+
+  using SwapchainHandle::operator=;
+
+  /**
+   * Initialises GraphicsSwapchain
+   */
+  void Initialise();
+
+  /**
+   * Acquires next renderable frame from swapchain
+   */
+  void AcquireFrame();
+
+  /**
+   * Presents current frame
+   */
+  void PresentFrame();
+};
+}
+}
+
+#endif //DALI_CORE_GRAPHICSSWAPCHAIN_H
diff --git a/dali/graphics/integration/graphics-logical-device-base.h b/dali/graphics/integration/graphics-logical-device-base.h
new file mode 100644 (file)
index 0000000..ec1ac96
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef DALI_CORE_GRAPHICS_GRAPHICS_LOGICAL_DEVICE_BASE_H
+#define DALI_CORE_GRAPHICS_GRAPHICS_LOGICAL_DEVICE_BASE_H
+
+/*
+ * Copyright (c) 2017 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/graphics/graphics-swapchain.h>
+#include <dali/graphics/vulkan/common.h>
+#include <cinttypes>
+
+namespace Dali
+{
+namespace Graphics
+{
+class GraphicsPhysicalDevice;
+class GraphicsSurface;
+
+// base class for context implementation
+class GraphicsLogicalDeviceBase : public VkObject
+{
+public:
+  virtual bool Initialise() = 0;
+
+  virtual GraphicsSwapchain CreateSwapchain(const GraphicsSurface& surface,
+                                            uint32_t               bufferCount,
+                                            DepthStencil           depthStencil,
+                                            VSyncMode              enforceVSync) = 0;
+
+  virtual GraphicsPhysicalDevice GetGraphicsPhysicalDevice() const = 0;
+};
+
+} // Graphics
+} // Dali
+
+#endif //DALI_CORE_GRAPHICS_GRAPHICS_LOGICAL_DEVICE_BASE_H
diff --git a/dali/graphics/integration/graphics-physical-device-base.h b/dali/graphics/integration/graphics-physical-device-base.h
new file mode 100644 (file)
index 0000000..51d986a
--- /dev/null
@@ -0,0 +1,88 @@
+#ifndef DALI_CORE_GRAPHICS_PHYSCIAL_DEVICE_BASE_H
+#define DALI_CORE_GRAPHICS_PHYSCIAL_DEVICE_BASE_H
+
+/*
+ * Copyright (c) 2017 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/graphics/graphics-logical-device.h>
+#include <dali/graphics/graphics-surface.h>
+#include <dali/graphics/vulkan/common.h>
+namespace Dali
+{
+namespace Graphics
+{
+namespace Integration
+{
+
+// abstract class for building the graphics adaptor
+class GraphicsPhysicalDeviceBase : public VkObject
+{
+public:
+  /**
+   *
+   * @param extensions
+   * @param layers
+   * @return
+   */
+  virtual bool Initialise(const ExtensionNameList& extensions, const ValidationLayerFlags2& layers) = 0;
+
+  /**
+   *
+   * @param instanceExtensionName
+   * @return
+   */
+  virtual bool IsExtensionAvailable(const std::string& instanceExtensionName) = 0;
+
+  /**
+   *
+   * @param instanceExtensionName
+   * @return
+   */
+  virtual bool IsLayerAvailable(const std::string& instanceExtensionName) = 0;
+
+  /**
+   *
+   * @param surface
+   * @return
+   */
+  virtual GraphicsLogicalDevice CreateLogicalDevice(const ExtensionNameList& enabledExtensions) = 0;
+
+  /**
+   *
+   * @param flags
+   * @return
+   */
+  virtual bool ChoosePhysicalDevice(const PhysicalDeviceFlags& flags) = 0;
+
+  /**
+   *
+   * @param flags
+   */
+  virtual void SetValidationDebugChannels(const ValidationChannelFlags& flags) = 0;
+
+  /**
+   *
+   * @param info
+   * @return
+   */
+  virtual GraphicsSurface CreateSurface(const NativeSurfaceCreateInfo& info) = 0;
+};
+} // Integration
+} // Graphics
+} // Dali
+
+#endif //DALI_CORE_GRAPHICS_PHYSCIAL_DEVICE_BASE_H
diff --git a/dali/graphics/integration/graphics-surface-base.h b/dali/graphics/integration/graphics-surface-base.h
new file mode 100644 (file)
index 0000000..254039b
--- /dev/null
@@ -0,0 +1,67 @@
+#ifndef DALI_CORE_GRAPHICS_SURFACE_BASE_H
+#define DALI_CORE_GRAPHICS_SURFACE_BASE_H
+
+/*
+ * Copyright (c) 2017 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/graphics/vulkan/common.h>
+
+namespace Dali
+{
+namespace Graphics
+{
+class GraphicsPhysicalDevice;
+
+namespace Vulkan
+{
+
+namespace Internal
+{
+class GraphicsSurfaceBase : public VkObject
+{
+private:
+  GraphicsSurfaceBase() = default;
+
+public:
+  //GraphicsSurfaceBase(const GraphicsPhysicalDevice &adaptor)
+  //{};
+  GraphicsSurfaceBase(const GraphicsPhysicalDevice &physicalDevice){};
+  virtual ~GraphicsSurfaceBase() = default;
+
+  virtual bool Initialise() = 0;
+
+  virtual bool Replace() = 0;
+
+  virtual bool Destroy() = 0;
+
+  virtual uint32_t GetWidth() = 0;
+
+  virtual uint32_t GetHeight() = 0;
+};
+}
+
+} // Vulkan
+
+// todo: remove 'internal' namespace
+namespace Integration
+{
+using GraphicsSurfaceBase = Vulkan::Internal::GraphicsSurfaceBase;
+} // Integration
+} // Graphics
+} // Dali
+
+#endif // DALI_CORE_GRAPHICS_SURFACE_BASE_H
diff --git a/dali/graphics/integration/graphics-swapchain-base.h b/dali/graphics/integration/graphics-swapchain-base.h
new file mode 100644 (file)
index 0000000..8128005
--- /dev/null
@@ -0,0 +1,61 @@
+#ifndef DALI_CORE_GRAPHICS_SWAPCHAIN_BASE_H
+#define DALI_CORE_GRAPHICS_SWAPCHAIN_BASE_H
+
+/*
+ * Copyright (c) 2017 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/graphics/vulkan/common.h>
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace Integration
+{
+
+class GraphicsSwapchainBase : public VkObject
+{
+public:
+  GraphicsSwapchainBase() = default;
+  virtual ~GraphicsSwapchainBase() = default;
+
+  /**
+   * Initialises swapchain
+   * @return
+   */
+  virtual bool Initialise() = 0;
+
+  /**
+   * Called for new frame to acquire new frame buffer
+   * @return
+   */
+  virtual bool AcquireFrame() = 0;
+
+  /**
+   * Called at the end of frame to present current frame buffer
+   * @return
+   */
+  virtual bool PresentFrame() = 0;
+
+};
+
+} // Integration
+} // Graphics
+} // Dali
+
+
+#endif // DALI_CORE_GRAPHICS_SWAPCHAIN_BASE_H
diff --git a/dali/graphics/vulkan-api-test.cpp b/dali/graphics/vulkan-api-test.cpp
new file mode 100644 (file)
index 0000000..a46f50b
--- /dev/null
@@ -0,0 +1,381 @@
+//
+// Created by adam.b on 23/03/17.
+//
+
+#include <vulkan/vulkan.hpp>
+#ifdef __linux__
+#include <X11/Xlib.h>
+#include <unistd.h>
+#endif
+
+
+#include <dali/graphics/graphics-physical-device.h>
+#include <dali/graphics/vulkan/physical-device.h>
+#include <dali/graphics/vulkan/surface/xcb-surface.h>
+#include <dali/graphics/vulkan/surface/xlib-surface.h>
+
+// vulkan specific
+#include <dali/graphics/vulkan/command-queue.h>
+#include <dali/graphics/vulkan/device-memory.h>
+#include <dali/graphics/vulkan/image.h>
+#include <dali/graphics/vulkan/logical-device.h>
+#include <dali/graphics/vulkan/swapchain.h>
+
+using namespace Dali::Graphics;
+
+namespace
+{
+Vulkan::CommandPool gSecondaryCommandPool{nullptr};
+Vulkan::Image       gImage{nullptr};
+}
+
+struct TestWindow
+{
+  int      width, height;
+  Display* display;
+  ::Window window;
+  int      defaultScreen;
+} gWnd;
+
+void InitWindow(int width, int height)
+{
+  // 1. Create Window ( done by DALI
+  gWnd.width         = width;
+  gWnd.height        = height;
+  gWnd.display       = XOpenDisplay(nullptr);
+  gWnd.defaultScreen = DefaultScreen(gWnd.display);
+  gWnd.window = XCreateSimpleWindow(gWnd.display, RootWindow(gWnd.display, gWnd.defaultScreen), 0, 0,
+                                    gWnd.width, gWnd.height, 1, BlackPixel(gWnd.display, gWnd.defaultScreen),
+                                    WhitePixel(gWnd.display, gWnd.defaultScreen));
+
+  XSelectInput(gWnd.display, gWnd.window, ExposureMask | KeyPressMask);
+  XMapWindow(gWnd.display, gWnd.window);
+}
+
+struct XcbWindow
+{
+  xcb_connection_t* xcb_connection;
+  xcb_screen_t*     xcb_screen;
+  xcb_window_t      xcb_window;
+  int               width, height;
+} gXcb;
+
+void initXcbWindow(int width, int height)
+{
+  // 1. Create Window ( done by DALi )
+  gXcb.width  = width;
+  gXcb.height = height;
+  int                   screenNum(0);
+  xcb_connection_t*     connection = xcb_connect(NULL, &screenNum);
+  const xcb_setup_t*    setup      = xcb_get_setup(connection);
+  xcb_screen_iterator_t iter       = xcb_setup_roots_iterator(setup);
+  for(int i = 0; i < screenNum; ++i)
+    xcb_screen_next(&iter);
+
+  xcb_screen_t* screen = iter.data;
+  xcb_window_t  window = xcb_generate_id(connection);
+
+  uint32_t mask     = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
+  uint32_t values[] = {screen->white_pixel, XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS};
+
+  xcb_create_window(connection, XCB_COPY_FROM_PARENT, window, screen->root, 0, 0, gXcb.width,
+                    gXcb.height, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual, mask, values);
+
+  xcb_map_window(connection, window);
+  const uint32_t coords[] = {100, 100};
+  xcb_configure_window(connection, window, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, coords);
+  xcb_flush(connection);
+
+  gXcb.xcb_connection = connection;
+  gXcb.xcb_window     = window;
+  gXcb.xcb_screen     = screen;
+}
+
+void createTexture(const Vulkan::LogicalDevice& device, const Vulkan::CommandBuffer& commandBuffer)
+{
+  // create buffer
+  const int TEXTURE_SIZE = 1024 * 1024 * 4;
+
+  vk::BufferCreateInfo bufInfo;
+  bufInfo.setUsage(vk::BufferUsageFlagBits::eTransferSrc)
+      .setSharingMode(vk::SharingMode::eExclusive)
+      .setQueueFamilyIndexCount(0)
+      .setPQueueFamilyIndices(nullptr)
+      .setSize(TEXTURE_SIZE);
+
+  auto textureBuffer = Vulkan::Buffer::New(device, bufInfo);
+  auto memory = device.AllocateBufferMemory(textureBuffer, vk::MemoryPropertyFlagBits::eHostVisible, true);
+  void* ptr = memory.Map(0, VK_WHOLE_SIZE);
+
+  // Load texture directly into the buffer
+  FILE* f = fopen("/tmp/out.rgba", "rb");
+  fseek(f, 0, SEEK_END);
+  assert(ftell(f) == bufInfo.size);
+  fseek(f, 0, SEEK_SET);
+  fread(ptr, 1, bufInfo.size, f);
+  fclose(f);
+
+  // unmap and flush memory
+  memory.Unmap();
+  memory.Flush();
+
+  // create 2D texture image
+  vk::ImageCreateInfo imageInfo;
+  imageInfo.setSharingMode(vk::SharingMode::eExclusive);
+  imageInfo.setUsage(vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferSrc | vk::ImageUsageFlagBits::eTransferDst);
+  imageInfo.setInitialLayout(vk::ImageLayout::eUndefined);
+  imageInfo.setSamples(vk::SampleCountFlagBits::e1);
+  imageInfo.setExtent(vk::Extent3D{1024, 1024, 1});
+  imageInfo.setFormat(vk::Format::eR8G8B8A8Unorm);
+  imageInfo.setTiling(vk::ImageTiling::eOptimal);
+  imageInfo.setMipLevels(1);
+  imageInfo.setArrayLayers(1);
+  imageInfo.setImageType(vk::ImageType::e2D);
+
+  // create vulkan image
+  auto image       = Vulkan::Image::New(device, imageInfo);
+  auto imageMemory = device.AllocateImageMemory(image, vk::MemoryPropertyFlagBits::eDeviceLocal, true);
+
+  if(!gSecondaryCommandPool)
+  {
+    gSecondaryCommandPool = device.CreateCommandPool(QueueType::TRANSFER, true, true);
+  }
+
+  // record
+  Vulkan::CommandBuffer cmdBuf = gSecondaryCommandPool.AllocateCommandBuffer(true);
+  vk::BufferImageCopy   region;
+  region.setImageExtent({1024, 1024, 1});
+  region.setImageSubresource(vk::ImageSubresourceLayers()
+                                 .setAspectMask(vk::ImageAspectFlagBits::eColor)
+                                 .setMipLevel(0)
+                                 .setLayerCount(1)
+                                 .setBaseArrayLayer(0));
+
+  auto layoutBarrier =
+      image.GetLayoutChangeBarrier(vk::ImageLayout::eTransferDstOptimal, vk::AccessFlags(),
+                                   vk::AccessFlagBits::eTransferWrite, vk::ImageAspectFlagBits::eColor);
+
+  cmdBuf.Begin(true);
+  cmdBuf->pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTopOfPipe,
+                          vk::DependencyFlags(), 0, nullptr, 0, nullptr, 1, &layoutBarrier);
+  cmdBuf->copyBufferToImage(*textureBuffer, *image, vk::ImageLayout::eTransferDstOptimal, 1, &region);
+
+  image.SetLayout( vk::ImageLayout::eTransferDstOptimal );
+  auto layoutBarrier2 =
+  image.GetLayoutChangeBarrier(vk::ImageLayout::eTransferSrcOptimal, vk::AccessFlags(),
+                               vk::AccessFlagBits::eTransferWrite, vk::ImageAspectFlagBits::eColor);
+
+
+  cmdBuf->pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTopOfPipe,
+                          vk::DependencyFlags(), 0, nullptr, 0, nullptr, 1, &layoutBarrier2);
+
+  image.SetLayout( vk::ImageLayout::eTransferSrcOptimal );
+  cmdBuf.End();
+
+  auto queue = device.GetCommandQueue(0, QueueType::TRANSFER);
+  queue.Submit(&cmdBuf, 1, nullptr);
+
+  // should use fence
+  queue.WaitIdle();
+
+  gImage = image;
+  return;
+}
+
+int main(int argc, char** argv)
+{
+
+  InitWindow(720, 360);
+  // make physical device from vulkan device ( should be done through some sort of
+  // implementation factory )
+  GraphicsPhysicalDevice physDevice(Vulkan::PhysicalDevice::New());
+  ExtensionNameList      list;
+
+  // check extensions ( vulkan specific )
+
+  NativeSurfaceType surfaceType = NativeSurfaceType::UNDEFINED;
+
+  if(physDevice.IsExtensionAvailable(VK_KHR_SURFACE_EXTENSION_NAME))
+    list.emplace_back(VK_KHR_SURFACE_EXTENSION_NAME);
+  if(physDevice.IsExtensionAvailable(VK_KHR_XCB_SURFACE_EXTENSION_NAME))
+  {
+    list.emplace_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
+    //surfaceType = NativeSurfaceType::XCB;
+  }
+  if(physDevice.IsExtensionAvailable(VK_KHR_XLIB_SURFACE_EXTENSION_NAME))
+  {
+    list.emplace_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
+    if(surfaceType == NativeSurfaceType::UNDEFINED)
+      surfaceType = NativeSurfaceType::X11;
+  }
+
+  physDevice.Initialise(list,
+                        ValidationLayerFlags2() | ValidationLayerBit2::CORE_VALIDATION |
+                            ValidationLayerBit2::STANDARD_VALIDATION |
+                            ValidationLayerBit2::PARAMETER_VALIDATION | ValidationLayerBit2::API_DUMP);
+
+  // reporting on all channels
+  //physDevice.SetValidationDebugChannels(ValidationChannelBit::ALL);
+
+  bool result = physDevice.ChoosePhysicalDevice(PhysicalDeviceBit::ANY);
+
+  GraphicsSurface surface{nullptr};
+
+  if(surfaceType == NativeSurfaceType::XCB)
+  {
+    XcbSurfaceCreateInfo info;
+    info.connection = gXcb.xcb_connection;
+    info.window     = gXcb.xcb_window;
+    surface         = physDevice.CreateSurface(info);
+  }
+  else
+  {
+    XlibSurfaceCreateInfo info;
+    info.display    = gWnd.display;
+    info.window     = gWnd.window;
+    surface         = physDevice.CreateSurface(info);
+  }
+  auto logicalDevice = physDevice.CreateLogicalDevice();
+
+  auto swapchain = logicalDevice.CreateSwapchain(surface, 2, DepthStencil::NONE, VSyncMode::DISABLED);
+
+  // obtain vulkan interface
+  auto vkSwapchain = swapchain.Cast< Vulkan::Swapchain >();
+  auto vkDevice    = logicalDevice.Cast< Vulkan::LogicalDevice >();
+
+  createTexture(vkDevice, vkSwapchain.GetCurrentCommandBuffer());
+
+  bool running = true;
+
+  while(running)
+  {
+    swapchain.AcquireFrame();
+    auto          cmdbuf = vkSwapchain.GetCurrentCommandBuffer();
+    vk::ImageCopy region;
+
+    vk::ImageSubresourceLayers subres;
+    subres.setBaseArrayLayer(0).setAspectMask(vk::ImageAspectFlagBits::eColor).setLayerCount(1).setMipLevel(0);
+
+    region.setExtent({100, 100, 1})
+        .setDstOffset({0, 0, 0})
+        .setSrcOffset({0, 0, 0})
+        .setSrcSubresource(subres)
+        .setDstSubresource(subres);
+
+    cmdbuf->copyImage(*gImage, gImage.GetLayout(), vkSwapchain.GetCurrentImage(),
+                                               vk::ImageLayout::eColorAttachmentOptimal, 1, &region);
+    usleep(1000);
+    swapchain.PresentFrame();
+  }
+
+  return 0;
+}
+
+int main_(int argc, char** argv)
+{
+  initXcbWindow(720, 360);
+
+#if 0
+  // using template argument to pick adaptor implementation
+  GraphicsPhysicalDevice   adaptor = GraphicsPhysicalDevice::GraphicsPhysicalDevice< Internal::VulkanAdaptor >();
+  ExtensionNameList list;
+
+  // check extension
+  if(adaptor.IsExtensionAvailable(VK_KHR_SURFACE_EXTENSION_NAME))
+    list.emplace_back(VK_KHR_SURFACE_EXTENSION_NAME);
+  if(adaptor.IsExtensionAvailable(VK_KHR_XLIB_SURFACE_EXTENSION_NAME))
+    list.emplace_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
+  if(adaptor.IsExtensionAvailable(VK_KHR_XCB_SURFACE_EXTENSION_NAME))
+    list.emplace_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
+
+  // initialise
+  adaptor.Initialise(list,
+                     ValidationLayerFlags()
+  | ValidationLayerBit2::CORE_VALIDATION |
+                         ValidationLayerBit2::STANDARD_VALIDATION |
+                         ValidationLayerBit2::PARAMETER_VALIDATION | ValidationLayerBit2::API_DUMP);
+
+  // reporting on all channels
+  adaptor.SetValidationDebugChannels(ValidationChannelBit::ALL);
+
+  // choose first available physical adaptor
+  bool result = adaptor.ChoosePhysicalDevice(PhysicalDeviceBit::ANY);
+
+  if(!result) // no requested device available ( maybe adding enumeration )
+  {
+    // fixme, something went very wrong
+  }
+
+  // create surface for X11 ( could be templated GraphicsPhysicalDevice function? )
+  auto surface = adaptor.CreateSurface< Internal::GraphicsXcbSurface >(adaptor, gXcb.xcb_connection, gXcb.xcb_window);
+
+  if(!surface)
+  {
+    VkLog("No surface dammit!");
+  }
+
+  // create context
+  auto context = adaptor.CreateContext(surface);
+
+  // create swapchain ( 2 buffers )
+  auto swapchain = context.CreateSwapchain(surface, 3, DepthStencil::NONE, true);
+
+  while( 1 )
+  {
+    swapchain.AcquireFrame();
+    usleep(1000);
+    //swapchain.SwapBuffers( true );
+    swapchain.PresentFrame();
+  }
+
+  return 0;
+}
+
+int _main(int argc, char** argv)
+{
+#if 0
+  InitWindow(720, 360);
+
+  GraphicsPhysicalDevice adaptor;
+  ExtensionNameList list;
+
+  // check extension
+  if(adaptor.IsExtensionAvailable(VK_KHR_SURFACE_EXTENSION_NAME))
+    list.emplace_back(VK_KHR_SURFACE_EXTENSION_NAME);
+  if(adaptor.IsExtensionAvailable(VK_KHR_XLIB_SURFACE_EXTENSION_NAME))
+    list.emplace_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
+
+  // initialise
+  adaptor.Initialise(list, ValidationLayerFlags() |
+                    ValidationLayerBit2::CORE_VALIDATION | ValidationLayerBit2::STANDARD_VALIDATION |
+  ValidationLayerBit2::PARAMETER_VALIDATION|ValidationLayerBit2::API_DUMP);
+
+  // reporting on all channels
+  adaptor.SetValidationDebugChannels( ValidationChannelBit::ALL );
+
+  // choose first available physical adaptor
+  bool result = adaptor.ChoosePhysicalDevice(PhysicalDeviceBit::ANY);
+
+  if( !result ) // no requested device available ( maybe adding enumeration )
+  {
+    // fixme, something went very wrong
+  }
+
+  // create surface for X11 ( could be templated GraphicsPhysicalDevice function? )
+  //auto& surface = GraphicsSurfaceBase::CreateSurface<GraphicsXlibSurface>( adaptor, gWnd.display, gWnd.window );
+  auto& surface = adaptor.CreateSurface<GraphicsXlibSurface>( adaptor, gWnd.display, gWnd.window );
+
+  if( surface == nullptr )
+  {
+    // surface invalid :((((
+  }
+  // create context
+  GraphicsContext context = adaptor.CreateContext(surface);
+
+  // create swapchain with 2 buffers
+  GraphicsSwapchain swapchain = context.CreateSwapchain( surface, 2 );
+
+#endif
+#endif
+  return 0;
+}
\ No newline at end of file
diff --git a/dali/graphics/vulkan/buffer.cpp b/dali/graphics/vulkan/buffer.cpp
new file mode 100644 (file)
index 0000000..03ea44a
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2017 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/graphics/vulkan/buffer.h>
+#include <dali/graphics/vulkan/device-memory.h>
+#include <dali/graphics/vulkan/logical-device.h>
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace Vulkan
+{
+// Implementation
+
+class BufferImpl : public VkObject
+{
+public:
+  BufferImpl(const LogicalDevice& device, const vk::BufferCreateInfo& info)
+  : mDevice(device), mCreateInfo(info)
+  {
+  }
+
+  virtual ~BufferImpl();
+
+  bool Initialise();
+
+  const vk::Buffer& GetVkBuffer() const
+  {
+    return mBuffer;
+  }
+
+  const DeviceMemory& GetDeviceMemory() const
+  {
+    return mDeviceMemory;
+  }
+
+  bool BindDeviceMemory(const DeviceMemory& memory, size_t offset);
+
+private:
+  LogicalDevice        mDevice{nullptr};
+  DeviceMemory         mDeviceMemory{nullptr}; // bound device memory
+  vk::BufferCreateInfo mCreateInfo{};
+  vk::Buffer           mBuffer{nullptr};
+  size_t               mMemoryBoundOffset{0u};
+};
+
+BufferImpl::~BufferImpl()
+{
+  if(mBuffer)
+  {
+    mDevice.GetVkDevice().destroyBuffer(mBuffer, mDevice.GetVkAllocator());
+  }
+}
+
+bool BufferImpl::Initialise()
+{
+  return VkTestBool(mDevice.GetVkDevice().createBuffer(&mCreateInfo, mDevice.GetVkAllocator(), &mBuffer));
+}
+
+bool BufferImpl::BindDeviceMemory(const DeviceMemory& memory, size_t offset)
+{
+  assert(!mDeviceMemory && "There is a DeviceMemory already bound!");
+  if(VkTestBool(mDevice->bindBufferMemory(mBuffer, *memory, offset)))
+  {
+    mDeviceMemory      = memory;
+    mMemoryBoundOffset = offset;
+    return true;
+  }
+  return false;
+}
+
+// Handle
+namespace
+{
+BufferImpl* GetImpl(Buffer* handle)
+{
+  return static_cast< BufferImpl* >(handle->GetObject());
+}
+BufferImpl* GetImpl(const Buffer* handle)
+{
+  return static_cast< BufferImpl* >(handle->GetObject());
+}
+}
+
+Buffer Buffer::New(const LogicalDevice& device, const vk::BufferCreateInfo& info)
+{
+  auto impl = new BufferImpl(device, info);
+  if(impl->Initialise())
+  {
+    return impl;
+  }
+  return nullptr;
+}
+
+const vk::Buffer& Buffer::GetVkResource() const
+{
+  return GetImpl(this)->GetVkBuffer();
+}
+
+const vk::Buffer& Buffer::operator*() const
+{
+  return GetImpl(this)->GetVkBuffer();
+}
+
+bool Buffer::BindDeviceMemory(const DeviceMemory& memory)
+{
+  return GetImpl(this)->BindDeviceMemory(memory, 0);
+}
+
+bool Buffer::BindDeviceMemory(const DeviceMemory& memory, size_t offset)
+{
+  return GetImpl(this)->BindDeviceMemory(memory, offset);
+}
+}
+}
+}
\ No newline at end of file
diff --git a/dali/graphics/vulkan/buffer.h b/dali/graphics/vulkan/buffer.h
new file mode 100644 (file)
index 0000000..db17538
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef DALI_CORE_GRAPHICS_VULKAN_BUFFER_H
+#define DALI_CORE_GRAPHICS_VULKAN_BUFFER_H
+
+/*
+ * Copyright (c) 2017 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/graphics/vulkan/common.h>
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace Vulkan
+{
+
+class Buffer : public VkHandle
+{
+public:
+  Buffer(VkObject* impl = nullptr) : VkHandle(impl){}
+  using VkHandle::operator=;
+
+  static Buffer New( const class LogicalDevice& device, const vk::BufferCreateInfo& info );
+
+  const vk::Buffer& GetVkResource() const;
+  const vk::Buffer& operator*() const;
+
+  bool BindDeviceMemory( const class DeviceMemory& memory );
+
+  bool BindDeviceMemory( const class DeviceMemory& memory, size_t offset );
+
+
+
+};
+
+} // namespace Vulkan
+
+} // namespace Graphics
+
+} // namespace Dali
+
+#endif // DALI_CORE_GRAPHICS_VULKAN_BUFFER_H
diff --git a/dali/graphics/vulkan/command-buffer.cpp b/dali/graphics/vulkan/command-buffer.cpp
new file mode 100644 (file)
index 0000000..7d58e3e
--- /dev/null
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2017 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/graphics/vulkan/command-buffer.h>
+#include <dali/graphics/vulkan/command-pool.h>
+#include <dali/graphics/vulkan/logical-device.h>
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace Vulkan
+{
+using State = CommandBufferState;
+class CommandBufferImpl : public VkObject
+{
+public:
+  CommandBufferImpl(const LogicalDevice& context, const CommandPool& pool,
+                    vk::CommandBufferLevel level, vk::CommandBuffer buffer)
+  : VkObject{}, mPool{pool}, mDevice{context}, mBuffer{buffer}, mLevel{level}
+  {
+  }
+
+  bool OnSafeDelete() override
+  {
+    // mind that the resources may not be released if the pool doesn't allow
+    // freeing a single command buffer! Synchronization is explicit
+    if(mPool)
+    {
+      mDevice.GetVkDevice().freeCommandBuffers(mPool.GetCommandPool(), 1, &mBuffer);
+      return true;
+    }
+    else
+    {
+      return false;
+    }
+  }
+
+  const vk::CommandBuffer& GetVkCommandBuffer() const
+  {
+    return mBuffer;
+  }
+
+  const CommandPool& GetCommandPool() const
+  {
+    return mPool;
+  }
+
+  State GetState() const
+  {
+    return mState;
+  }
+
+  bool Begin(bool oneTimeSubmit, bool renderPassContinue, bool simultaneousUse);
+  bool End();
+  bool Free();
+  bool Reset();
+
+private:
+  CommandPool            mPool;
+  LogicalDevice          mDevice;
+  vk::CommandBuffer      mBuffer;
+  vk::CommandBufferLevel mLevel;
+
+  // state of command buffer
+  State mState{State::UNDEFINED};
+};
+
+bool CommandBufferImpl::Begin(bool oneTimeSubmit, bool renderPassContinue, bool simultaneousUse)
+{
+  // check state
+  if(mState != State::CREATED && mState != State::UNDEFINED && mState != State::RESET)
+  {
+    VkLog("[VKCMDBUF] Invalid buffer state: %d", static_cast< int >(mState));
+    return false;
+  }
+
+  vk::CommandBufferUsageFlags flags{};
+  if(oneTimeSubmit)
+  {
+    flags |= vk::CommandBufferUsageFlagBits::eOneTimeSubmit;
+  }
+  if(renderPassContinue)
+  {
+    flags |= vk::CommandBufferUsageFlagBits::eRenderPassContinue;
+  }
+  if(simultaneousUse)
+  {
+    flags |= vk::CommandBufferUsageFlagBits::eSimultaneousUse;
+  }
+
+  // todo implement inheritance
+  vk::CommandBufferBeginInfo info;
+  info.setFlags(flags).setPInheritanceInfo(nullptr);
+
+  if(VkTestCall(mBuffer.begin(&info)) == vk::Result::eSuccess)
+  {
+    mState = State::RECORDING;
+    return true;
+  }
+
+  return false;
+}
+
+bool CommandBufferImpl::End()
+{
+  // check state
+  if(mState != State::RECORDING)
+  {
+    VkLog("[VKCMDBUF] Invalid buffer state: %d, it must be RECORDING", static_cast< int >(mState));
+    return false;
+  }
+
+  if(VkTestCall(mBuffer.end()) == vk::Result::eSuccess)
+  {
+    mState = State::RECORDED;
+    return true;
+  }
+  return false;
+}
+
+bool CommandBufferImpl::Free()
+{
+  // todo
+  assert(false && "CommandBufferImpl::Free() unimplemented!");
+}
+
+bool CommandBufferImpl::Reset()
+{
+  if(vk::Result::eSuccess == VkTestCall(mBuffer.reset(vk::CommandBufferResetFlagBits::eReleaseResources)))
+  {
+    mState = State::RESET;
+  }
+  return true;
+}
+
+// Implementation getter
+namespace
+{
+CommandBufferImpl* GetImpl(CommandBuffer* handle)
+{
+  return static_cast< CommandBufferImpl* >(handle->GetObject());
+}
+CommandBufferImpl* GetImpl(const CommandBuffer* handle)
+{
+  return static_cast< CommandBufferImpl* >(handle->GetObject());
+}
+}
+
+const vk::CommandBuffer* CommandBuffer::operator->() const
+{
+  auto& vkcmdbuf = GetImpl(this)->GetVkCommandBuffer();
+  return &vkcmdbuf;
+}
+
+std::vector< CommandBuffer > CommandBuffer::New(const CommandPool& pool, bool isPrimary, uint32_t count)
+{
+  auto vkDevice = pool.GetLogicalDevice().GetVkDevice();
+
+  std::vector< vk::CommandBuffer > buffers(count);
+
+  auto bufferLevel = isPrimary ? vk::CommandBufferLevel::ePrimary : vk::CommandBufferLevel::eSecondary;
+
+  {
+    vk::CommandBufferAllocateInfo info;
+    info.setCommandBufferCount(count).setCommandPool(pool.GetCommandPool()).setLevel(bufferLevel);
+
+    VkAssertCall(vkDevice.allocateCommandBuffers(&info, buffers.data()));
+  }
+
+  // move buffers data
+  std::vector< CommandBuffer > output(buffers.size());
+
+  for(auto&& cmdbuf : buffers)
+  {
+    output.emplace_back(new CommandBufferImpl(pool.GetLogicalDevice(), pool, bufferLevel, cmdbuf));
+  }
+  return std::move(output);
+}
+
+CommandBuffer CommandBuffer::New(const CommandPool& pool, bool isPrimary)
+{
+  // todo make more efficient implementation
+  return CommandBuffer::New(pool, isPrimary, 1)[0];
+}
+
+bool CommandBuffer::Begin(bool oneTimeSubmit, bool renderPassContinue, bool simultaneousUse)
+{
+  return GetImpl(this)->Begin(oneTimeSubmit, renderPassContinue, simultaneousUse);
+}
+
+bool CommandBuffer::End()
+{
+  return GetImpl(this)->End();
+}
+
+bool CommandBuffer::Free()
+{
+  return GetImpl(this)->Free();
+}
+
+bool CommandBuffer::Reset()
+{
+  return GetImpl(this)->Reset();
+}
+
+CommandBufferState CommandBuffer::GetState() const
+{
+  return GetImpl(this)->GetState();
+}
+
+vk::CommandBuffer CommandBuffer::GetVkBuffer() const
+{
+  return GetImpl(this)->GetVkCommandBuffer();
+}
+
+const CommandPool& CommandBuffer::GetCommandPool() const
+{
+  return GetImpl(this)->GetCommandPool();
+}
+
+std::thread::id CommandBuffer::GetThreadId() const
+{
+  return std::thread::id{};
+}
+}
+}
+}
diff --git a/dali/graphics/vulkan/command-buffer.h b/dali/graphics/vulkan/command-buffer.h
new file mode 100644 (file)
index 0000000..6982c44
--- /dev/null
@@ -0,0 +1,73 @@
+#ifndef DALI_CORE_GRAPHICS_VULKAN_COMMAND_BUFFER_H
+#define DALI_CORE_GRAPHICS_VULKAN_COMMAND_BUFFER_H
+
+/*
+ * Copyright (c) 2017 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/graphics/vulkan/common.h>
+#include <thread>
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace Vulkan
+{
+
+enum class CommandBufferState
+{
+  UNDEFINED,
+  CREATED,
+  RESET,
+  RECORDING,
+  RECORDED,
+  SUBMITTED
+};
+
+class CommandPool;
+class CommandBuffer : public VkHandle
+{
+public:
+  CommandBuffer(VkObject* impl = nullptr) : VkHandle{impl}
+  {
+  }
+  using VkHandle::operator=;
+
+  static std::vector< CommandBuffer > New(const CommandPool& pool, bool isPrimary, uint32_t count);
+  static CommandBuffer New(const CommandPool& pool, bool isPrimary);
+
+  vk::CommandBuffer  GetVkBuffer() const;
+  const CommandPool& GetCommandPool() const;
+  std::thread::id    GetThreadId() const;
+
+  CommandBufferState GetCommandBufferState() const;
+
+  // operator -> allows to record commands directly into Vulkan command buffer
+  const vk::CommandBuffer* operator->() const;
+
+  bool Begin(bool oneTimeSubmit, bool renderPassContinue = false, bool simultaneousUse = false);
+  bool End();
+  bool Free();
+  bool Reset();
+
+  CommandBufferState GetState() const;
+};
+}
+}
+}
+
+#endif // DALI_CORE_GRAPHICS_VULKAN_COMMAND_BUFFER_H
diff --git a/dali/graphics/vulkan/command-pool.cpp b/dali/graphics/vulkan/command-pool.cpp
new file mode 100644 (file)
index 0000000..8765aca
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2017 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/graphics/vulkan/command-pool.h>
+#include <dali/graphics/vulkan/physical-device.h>
+#include <dali/graphics/vulkan/logical-device.h>
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace Vulkan
+{
+
+
+class CommandPoolImpl : public VkObject
+{
+public:
+  CommandPoolImpl(const LogicalDevice& device, QueueType type, bool isExclusive, bool createTransient,
+  bool createResetCommandBuffer)
+  : VkObject{},
+    mDevice{ device }, mExclusive{ isExclusive },
+    mResetFlag{ createResetCommandBuffer }, mTransientFlag{ createTransient },
+    mQueueType{ type }
+  {
+  }
+
+  virtual ~CommandPoolImpl() {};
+
+  bool Initialise();
+
+  const LogicalDevice& GetLogicalDevice() const
+  {
+    return mDevice;
+  }
+
+  // vk objects getters
+public:
+
+  const vk::CommandPool GetCommandPool() const
+  {
+    return mCommandPool;
+  }
+
+  const vk::CommandPoolCreateInfo& GetCommandPoolCreateInfo() const
+  {
+    return mCreateInfo;
+  }
+
+  bool IsExclusive() const
+  {
+    return mExclusive;
+  }
+
+  bool IsTransient() const
+  {
+    return mTransientFlag;
+  }
+
+  bool IsResetFlag() const
+  {
+    return mResetFlag;
+  }
+
+  QueueType GetQueueType() const
+  {
+    return mQueueType;
+  }
+
+  std::vector< CommandBuffer > AllocateCommandBuffers(uint32_t count, bool primary);
+
+private:
+
+  LogicalDevice mDevice { nullptr };
+
+  // vulkan specific
+  vk::CommandPool           mCommandPool{nullptr};
+  vk::CommandPoolCreateInfo mCreateInfo{};
+
+  std::thread::id           mThreadId; // used if exclusive
+
+  // queue properties
+  bool mExclusive{false};
+  bool mResetFlag{false};
+  bool mTransientFlag{false};
+
+  QueueType mQueueType;
+};
+
+bool CommandPoolImpl::Initialise()
+{
+  auto vkDevice = mDevice.GetVkDevice();
+  auto phDevice = mDevice.GetPhysicalDevice();
+
+  vk::CommandPoolCreateFlags flags{};
+  if( mResetFlag )
+  {
+    flags |= vk::CommandPoolCreateFlagBits::eResetCommandBuffer;
+  }
+  if( mTransientFlag )
+  {
+    flags |= vk::CommandPoolCreateFlagBits::eTransient;
+  }
+
+  vk::CommandPoolCreateInfo info;
+
+  info.setQueueFamilyIndex( phDevice.GetQueueFamilyIndex( mQueueType) );
+  info.flags = flags;
+  mCreateInfo = info;
+
+  VkAssertCall( vkDevice.createCommandPool( &info, mDevice.GetVkAllocator(), &mCommandPool ) );
+
+  VkLog("[VULKAN] CommandPoolImpl::Initialise() created!");
+
+  return true;
+}
+
+std::vector< CommandBuffer > CommandPoolImpl::AllocateCommandBuffers(uint32_t count, bool primary)
+{
+  return std::move(CommandBuffer::New( CommandPool(this), primary, count ));
+}
+
+CommandPool CommandPool::New(const LogicalDevice& device, QueueType type, bool isExclusive,
+                                         bool createTransient, bool createResetCommandBuffer)
+{
+  auto impl = new CommandPoolImpl(device, type, isExclusive, createTransient, createResetCommandBuffer);
+  CommandPool retval( impl );
+  if(!impl->Initialise())
+  {
+    retval = nullptr;
+  }
+  return retval;
+}
+
+
+// Implementation getter
+namespace
+{
+CommandPoolImpl* GetImpl( CommandPool* pool )
+{
+  return static_cast<CommandPoolImpl*>(pool->GetObject());
+}
+CommandPoolImpl* GetImpl( const CommandPool* pool )
+{
+  return static_cast<CommandPoolImpl*>(pool->GetObject());
+}
+}
+bool CommandPool::Initialise()
+{
+  return GetImpl(this)->Initialise();
+}
+
+const vk::CommandPool CommandPool::GetCommandPool() const
+{
+  return GetImpl(this)->GetCommandPool();
+}
+
+const vk::CommandPoolCreateInfo& CommandPool::GetVkCommandPoolCreateInfo() const
+{
+  return GetImpl(this)->GetCommandPoolCreateInfo();
+}
+
+const LogicalDevice& CommandPool::GetLogicalDevice() const
+{
+  return GetImpl(this)->GetLogicalDevice();
+}
+
+std::thread::id CommandPool::GetThreadId() const
+{
+  //return GetImplementation<CommandPoolImpl>(this)->mThreadId;
+  return std::thread::id();
+}
+
+void CommandPool::ThreadAttach()
+{
+
+}
+
+void CommandPool::ThreadDetach()
+{
+
+}
+
+
+std::vector< CommandBuffer > CommandPool::AllocateCommandBuffers(uint32_t count, bool primary)
+{
+  return std::move(GetImpl(this)->AllocateCommandBuffers( count, primary ));
+}
+
+CommandBuffer CommandPool::AllocateCommandBuffer(bool primary)
+{
+  return GetImpl(this)->AllocateCommandBuffers( 1, primary )[0];
+}
+
+
+}
+}
+}
diff --git a/dali/graphics/vulkan/command-pool.h b/dali/graphics/vulkan/command-pool.h
new file mode 100644 (file)
index 0000000..69dab02
--- /dev/null
@@ -0,0 +1,65 @@
+#ifndef DALI_CORE_VULKAN_COMMAND_POOL_H
+#define DALI_CORE_VULKAN_COMMAND_POOL_H
+
+/*
+ * Copyright (c) 2017 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/graphics/vulkan/command-buffer.h>
+#include <dali/graphics/vulkan/common.h>
+#include <thread>
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace Vulkan
+{
+class LogicalDevice;
+
+//using VulkanCommandBufferArray = std::vector< VulkanCommandBuffer >;
+
+class CommandPool : public VkHandle
+{
+public:
+  CommandPool(VkObject* impl = nullptr) : VkHandle{impl}
+  {
+  }
+  using VkHandle::operator=;
+
+  static CommandPool New(const LogicalDevice& context, QueueType type, bool isExclusive,
+                         bool createTransient, bool createResetCommandBuffer);
+
+  bool Initialise();
+
+  // attaching to thread will make sure that any attempt of using pool on the
+  // wrong thread will assert
+  void ThreadAttach();
+  void ThreadDetach();
+
+  const vk::CommandPool            GetCommandPool() const;
+  const LogicalDevice&             GetLogicalDevice() const;
+  const vk::CommandPoolCreateInfo& GetVkCommandPoolCreateInfo() const;
+  std::thread::id                  GetThreadId() const;
+
+  std::vector< CommandBuffer > AllocateCommandBuffers(uint32_t count, bool primary);
+  CommandBuffer AllocateCommandBuffer(bool primary);
+};
+}
+}
+}
+
+#endif //DALI_CORE_VULKANCOMMANDPOOL_H
diff --git a/dali/graphics/vulkan/command-queue.cpp b/dali/graphics/vulkan/command-queue.cpp
new file mode 100644 (file)
index 0000000..e090221
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2017 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/graphics/vulkan/command-queue.h>
+#include <dali/graphics/vulkan/logical-device.h>
+#include <dali/graphics/vulkan/physical-device.h>
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace Vulkan
+{
+class QueueImpl : public VkObject
+{
+public:
+  QueueImpl(const LogicalDevice& device, QueueType type, uint32_t queueIndex)
+  : VkObject{}, mDevice{device}, mType{type}, mQueue{nullptr}, mQueueIndex{queueIndex}
+  {
+  }
+
+  bool Initialise()
+  {
+    auto phDevice = mDevice.GetPhysicalDevice();
+    auto vkDevice = mDevice.GetVkDevice();
+
+    uint32_t familyIndex = static_cast< uint32_t >(phDevice.GetQueueFamilyIndex(mType));
+    vkDevice.getQueue(familyIndex, mQueueIndex, &mQueue);
+    return true;
+  }
+
+  bool Submit(const std::vector< CommandBuffer >& buffers, vk::Fence fence = nullptr)
+  {
+    return Submit(buffers.data(), static_cast< uint32_t >(buffers.size()), nullptr, 0, nullptr, 0, nullptr, fence);
+  }
+
+  bool Submit(const CommandBuffer* pBuffers, const uint32_t bufferCount,
+              const vk::Semaphore* pWaitSemaphores, const uint32_t waitSemaphoreCount,
+              const vk::Semaphore* pSignalSemaphores, const uint32_t signalSemaphoreCount,
+              const vk::PipelineStageFlags* pWaitDstStageFlags, vk::Fence fence)
+  {
+    // todo make temporary copy more efficient
+    auto vkBuffers = std::vector< vk::CommandBuffer >(bufferCount);
+    for(uint32_t index = 0; index < bufferCount; ++index)
+    {
+      vkBuffers[index] = pBuffers[index].GetVkBuffer();
+    }
+
+    if(fence)
+    {
+      mDevice.GetVkDevice().resetFences(1, &fence);
+    }
+
+    vk::SubmitInfo info;
+    info.setCommandBufferCount(bufferCount)
+        .setPCommandBuffers(vkBuffers.data())
+        .setWaitSemaphoreCount(waitSemaphoreCount)
+        .setPWaitSemaphores(pWaitSemaphores)
+        .setSignalSemaphoreCount(signalSemaphoreCount)
+        .setPSignalSemaphores(pSignalSemaphores)
+        .setPWaitDstStageMask(pWaitDstStageFlags);
+
+    if(VkTestCall(mQueue.submit(1, &info, fence)) != vk::Result::eSuccess)
+    {
+      return false;
+    }
+    return true;
+  }
+
+  void WaitIdle() const
+  {
+    mQueue.waitIdle();
+  }
+
+  LogicalDevice mDevice;
+  QueueType     mType;
+  vk::Queue     mQueue;
+  uint32_t      mQueueIndex;
+};
+
+namespace
+{
+QueueImpl* GetImpl(const CommandQueue* queue)
+{
+  return static_cast< QueueImpl* >(queue->GetObject());
+}
+QueueImpl* GetImpl(CommandQueue* queue)
+{
+  return static_cast< QueueImpl* >(queue->GetObject());
+}
+}
+
+CommandQueue CommandQueue::Get(const LogicalDevice& device, QueueType type, uint32_t queueIndex)
+{
+  auto impl = new QueueImpl(device, type, queueIndex);
+  impl->Initialise();
+  CommandQueue retval(impl);
+  return retval;
+}
+
+vk::Queue CommandQueue::GetVkQueue() const
+{
+  return GetImpl(this)->mQueue;
+}
+
+uint32_t CommandQueue::GetIndex() const
+{
+  return GetImpl(this)->mQueueIndex;
+}
+
+QueueType CommandQueue::GetType() const
+{
+  return GetImpl(this)->mType;
+}
+
+bool CommandQueue::Submit(const std::vector< CommandBuffer >& buffers, vk::Fence fence)
+{
+  return GetImpl(this)->Submit(buffers, fence);
+}
+
+bool CommandQueue::Submit(const CommandBuffer* buffers, uint32_t count, vk::Fence fence)
+{
+  return GetImpl(this)->Submit(buffers, count, nullptr, 0, nullptr, 0, nullptr, fence);
+}
+
+bool CommandQueue::Submit(const CommandBuffer* pBuffers, const uint32_t bufferCount,
+                          const vk::Semaphore* pWaitSemaphores, const uint32_t waitSemaphoreCount,
+                          const vk::Semaphore* pSignalSemaphores, const uint32_t signalSemaphoreCount,
+                          const vk::PipelineStageFlags* pWaitDstStageFlags, vk::Fence fence) const
+{
+  return GetImpl(this)->Submit(pBuffers, bufferCount, pWaitSemaphores, waitSemaphoreCount,
+                               pSignalSemaphores, signalSemaphoreCount, pWaitDstStageFlags, fence);
+}
+
+void CommandQueue::WaitIdle() const
+{
+  GetImpl(this)->WaitIdle();
+}
+}
+}
+}
\ No newline at end of file
diff --git a/dali/graphics/vulkan/command-queue.h b/dali/graphics/vulkan/command-queue.h
new file mode 100644 (file)
index 0000000..d574116
--- /dev/null
@@ -0,0 +1,59 @@
+#ifndef DALI_CORE_GRAPHICS_VULKAN_COMMAND_QUEUE_H
+#define DALI_CORE_GRAPHICS_VULKAN_COMMAND_QUEUE_H
+
+/*
+ * Copyright (c) 2017 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/graphics/vulkan/common.h>
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace Vulkan
+{
+class CommandBuffer;
+class LogicalDevice;
+
+class CommandQueue : public VkHandle
+{
+public:
+  CommandQueue(VkObject* impl = nullptr) : VkHandle{impl}
+  {
+  }
+  using VkHandle::operator=;
+
+  static CommandQueue Get(const LogicalDevice& device, QueueType type, uint32_t queueIndex);
+
+  vk::Queue GetVkQueue() const;
+  uint32_t  GetIndex() const;
+  QueueType GetType() const;
+
+  bool Submit(const CommandBuffer* buffers, uint32_t count, vk::Fence fence);
+  bool Submit(const std::vector< CommandBuffer >& buffers, vk::Fence fence);
+  bool Submit(const CommandBuffer* pBuffers, const uint32_t bufferCount,
+              const vk::Semaphore* pWaitSemaphores, const uint32_t waitSemaphoreCount,
+              const vk::Semaphore* pSignalSemaphores, const uint32_t signalSemaphoreCount,
+              const vk::PipelineStageFlags* pWaitDstStageFlags, vk::Fence fence) const;
+
+  void WaitIdle() const;
+};
+}
+}
+}
+
+#endif // DALI_CORE_GRAPHICS_VULKAN_COMMAND_QUEUE_H
diff --git a/dali/graphics/vulkan/common.h b/dali/graphics/vulkan/common.h
new file mode 100644 (file)
index 0000000..949c0f5
--- /dev/null
@@ -0,0 +1,350 @@
+#ifndef DALI_CORE_GRAPHICS_VULKAN_COMMON_H
+#define DALI_CORE_GRAPHICS_VULKAN_COMMON_H
+
+/*
+ * Copyright (c) 2017 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 <vulkan/vulkan.hpp>
+
+#include <cassert>
+#include <cinttypes>
+#include <memory>
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace Vulkan
+{
+void VkLog(const char* format, ...);
+
+#define OBJECT_HANDLE(TYPE)\
+public:\
+  TYPE( VkObject* object = nullptr ) : VkHandle{ object }{}\
+  using VkHandle::operator=;
+
+
+#define VkAssert(var, message)                    \
+  {                                               \
+    if(var.result != vk::Result::eSuccess)        \
+    {                                             \
+      Dali::Graphics::Vulkan::VkLog("[Assert] %s", message);              \
+      assert(var.result == vk::Result::eSuccess); \
+    }                                             \
+  }
+
+#define VkAssertCall(call)                                          \
+  {                                                                 \
+    const auto& _result = call;                                            \
+    if(_result != vk::Result::eSuccess)                             \
+    {                                                               \
+      Dali::Graphics::Vulkan::VkLog("[VkAssertCall] %s:%d: %s", __FILE__, __LINE__, #call); \
+      assert(_result == vk::Result::eSuccess);                      \
+    }                                                               \
+  }
+
+#define VkAssertCallMsg(call, msg)                                           \
+  {                                                                          \
+    auto _result = call;                                                     \
+    if(_result != vk::Result::eSuccess)                                      \
+    {                                                                        \
+      Dali::Graphics::Vulkan::VkLog("[VkAssertCall] %s:%d: %s, %s", __FILE__, __LINE__, #call, msg); \
+      assert(_result == vk::Result::eSuccess);                               \
+    }                                                                        \
+  }
+
+inline vk::Result VkTestCallFn(vk::Result result, const char* file, const char* call, int line)
+{
+  if(result != vk::Result::eSuccess)
+  {
+    Dali::Graphics::Vulkan::VkLog("[VkTestCall] %s:%d: %s -> Result = %d", file, line, call, static_cast< int >(result));
+  }
+  return result;
+}
+
+#define VkTestCall(call) VkTestCallFn(call, __FILE__, #call, __LINE__)
+#define VkTestBool(call) (vk::Result::eSuccess == VkTestCallFn(call, __FILE__, #call, __LINE__))
+}
+
+// helper template to create relation between flags and bits
+template< typename BitType, typename FlagType = uint32_t >
+struct BitFlags
+{
+  BitFlags() = default;
+
+  BitFlags(FlagType f) : flags(f)
+  {
+  }
+
+  BitFlags(const BitType& bit)
+  {
+    flags = static_cast< FlagType >(bit);
+  }
+
+  operator FlagType()
+  {
+    return flags;
+  }
+
+  bool operator==(FlagType srcFlags) const
+  {
+    return srcFlags == flags;
+  }
+
+  bool operator!=(const FlagType& srcFlags) const
+  {
+    return srcFlags != flags;
+  }
+
+  BitFlags operator|(const BitType& bit)
+  {
+    return BitFlags(flags | static_cast< FlagType >(bit));
+  }
+
+  BitFlags& operator|=(const BitType& bit)
+  {
+    flags |= static_cast< FlagType >(bit);
+    return *this;
+  }
+
+  BitFlags operator&(const BitFlags& rhs) const
+  {
+    return FlagType{(rhs.flags & flags)};
+  }
+
+  BitFlags operator&(unsigned int rhs) const
+  {
+    return BitFlags{(rhs & flags)};
+  }
+
+  FlagType flags{0};
+};
+
+using ExtensionNameList = std::vector< const char* >;
+using LayerNameList     = std::vector< const char* >;
+
+// common for adaptor
+enum class ValidationLayerBit2
+{
+  NONE                 = 0,
+  SCREENSHOT           = (1 << 0),
+  PARAMETER_VALIDATION = (1 << 1),
+  VKTRACE              = (1 << 2),
+  MONITOR              = (1 << 3),
+  SWAPCHAIN            = (1 << 4),
+  THREADING            = (1 << 5),
+  API_DUMP             = (1 << 6),
+  OBJECT_TRACKER       = (1 << 7),
+  CORE_VALIDATION      = (1 << 8),
+  UNIQUE_OBJECTS       = (1 << 9),
+  STANDARD_VALIDATION  = (1 << 10),
+  ALL                  = 0xFFFF
+};
+
+enum class ValidationChannelBit
+{
+  NONE                = 0,
+  INFORMATION         = (1 << 0),
+  WARNING             = (1 << 1),
+  PERFORMANCE_WARNING = (1 << 2),
+  ERROR               = (1 << 3),
+  DEBUG               = (1 << 4),
+  ALL                 = 0xFF
+};
+
+using ValidationLayerFlags2  = BitFlags< ValidationLayerBit2 >;
+using ValidationChannelFlags = BitFlags< ValidationChannelBit >;
+
+enum class PhysicalDeviceBit
+{
+  // physical device type
+  ANY        = 0,
+  DISCRETE   = (1 << 0),
+  INTEGRATED = (1 << 1)
+};
+
+using PhysicalDeviceFlags = BitFlags< PhysicalDeviceBit >;
+
+/// -----------------------------------------------------
+// vulkan only some sort of managed objects support
+//
+class VkObject
+{
+public:
+  VkObject()          = default;
+  virtual ~VkObject() = default;
+
+  uint32_t RetainRef()
+  {
+    return ++mObjectRefCount;
+  }
+
+  uint32_t ReleaseRef()
+  {
+    return --mObjectRefCount;
+  }
+
+  uint32_t GetRefCount()
+  {
+    return mObjectRefCount;
+  }
+
+  // handles releasing of vulkan object before being deleted
+  // or moved to discard queue
+  virtual bool OnSafeDelete()
+  {
+    return true;
+  }
+
+private:
+  uint32_t mObjectRefCount{0};
+};
+
+template< typename OBJECT >
+class VkHandleBase
+{
+public:
+  VkHandleBase() = default;
+  VkHandleBase(OBJECT* ptr)
+  {
+    mObject = ptr;
+    if(mObject)
+    {
+      static_cast< VkObject * >(mObject)->RetainRef();
+    }
+  }
+
+  VkHandleBase(const VkHandleBase& handle)
+  {
+    if(handle.mObject)
+    {
+      static_cast< VkObject * >(handle.mObject)->RetainRef();
+    }
+
+    mObject = handle.mObject;
+  }
+
+  virtual ~VkHandleBase()
+  {
+    if(mObject)
+    {
+      static_cast< VkObject* >(mObject)->ReleaseRef();
+      TrySafeDelete();
+    }
+  }
+
+  VkHandleBase& operator=(OBJECT* ptr)
+  {
+    if(mObject == ptr)
+    {
+      return *this;
+    }
+    if(mObject)
+    {
+      static_cast< VkObject* >(mObject)->ReleaseRef();
+      TrySafeDelete();
+    }
+    if(ptr)
+    {
+      static_cast< VkObject * >(ptr)->RetainRef();
+    }
+    mObject = ptr;
+    return *this;
+  }
+
+  VkHandleBase& operator=(const VkHandleBase& handle)
+  {
+    if(handle.mObject == mObject)
+    {
+      return *this;
+    }
+    if(mObject)
+    {
+      static_cast< VkObject* >(mObject)->ReleaseRef();
+      TrySafeDelete();
+    }
+    mObject = handle.mObject;
+    if(mObject)
+    {
+      static_cast< VkObject * >(mObject)->RetainRef();
+    }
+    return *this;
+  }
+
+  OBJECT* GetObject() const
+  {
+    return mObject;
+  }
+
+  operator bool() const
+  {
+    return mObject != nullptr;
+  }
+
+  bool operator!() const
+  {
+    return mObject == nullptr;
+  }
+
+  void Reset()
+  {
+    if(mObject)
+    {
+      static_cast< VkObject * >(mObject)->ReleaseRef();
+    }
+    TrySafeDelete();
+    mObject = nullptr;
+  }
+
+  bool TrySafeDelete()
+  {
+    if(!static_cast< VkObject* >(mObject)->GetRefCount())
+    {
+      if(static_cast< VkObject* >(mObject)->OnSafeDelete())
+      {
+        delete mObject;
+      }
+    }
+    // todo: deletion didn't go well, should be asserted?
+    return false;
+  }
+
+  template< typename T >
+  T Cast()
+  {
+    return T(dynamic_cast< OBJECT* >(mObject));
+  }
+
+protected:
+  OBJECT* mObject{nullptr};
+};
+
+using VkHandle = VkHandleBase< VkObject >;
+
+enum class QueueType : uint32_t
+{
+  GRAPHICS       = 0u,
+  COMPUTE        = 1u,
+  TRANSFER       = 2u,
+  SPARSE_BINDING = 3u,
+  PRESENT        = 4u,
+  END
+};
+}
+}
+
+#endif //DALI_CORE_GRAPHICS_VULKAN_COMMON_H
diff --git a/dali/graphics/vulkan/device-memory.cpp b/dali/graphics/vulkan/device-memory.cpp
new file mode 100644 (file)
index 0000000..19e4cf0
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2017 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/graphics/vulkan/device-memory.h>
+#include <dali/graphics/vulkan/logical-device.h>
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace Vulkan
+{
+
+class DeviceMemoryImpl : public VkObject
+{
+public:
+  DeviceMemoryImpl(const LogicalDevice& device, const vk::MemoryAllocateInfo& allocateInfo);
+
+  bool Initialise();
+
+  virtual bool OnSafeDelete();
+
+  const LogicalDevice& GetLogicalDevice() const
+  {
+    return mDevice;
+  }
+
+  const vk::DeviceMemory& GetVkDeviceMemory() const
+  {
+    return mMemory;
+  }
+
+  size_t GetSize() const
+  {
+    return mSize;
+  }
+
+  void* Map(size_t offset, size_t range);
+
+  void Unmap();
+
+  void Flush(size_t offset, size_t range);
+
+private:
+  LogicalDevice          mDevice{nullptr};
+  vk::MemoryAllocateInfo mAllocateInfo;
+  vk::DeviceMemory       mMemory{nullptr};
+  size_t                 mSize{0u};
+  void*                  mMappedPtr{nullptr};
+};
+
+// Implementation
+
+DeviceMemoryImpl::DeviceMemoryImpl(const LogicalDevice& device, const vk::MemoryAllocateInfo& allocateInfo)
+: mDevice(device), mAllocateInfo(allocateInfo), mMemory(nullptr), mSize(0u)
+{
+}
+
+bool DeviceMemoryImpl::Initialise()
+{
+  auto vkDevice    = mDevice.GetVkDevice();
+  auto vkAllocator = mDevice.GetVkAllocator();
+
+  VkAssertCall(vkDevice.allocateMemory(&mAllocateInfo, vkAllocator, &mMemory));
+
+  mSize = mAllocateInfo.allocationSize;
+  return true;
+}
+
+bool DeviceMemoryImpl::OnSafeDelete()
+{
+  if(mMemory)
+  {
+    mDevice.GetVkDevice().freeMemory(mMemory, mDevice.GetVkAllocator());
+    return true;
+  }
+  return false;
+}
+
+void* DeviceMemoryImpl::Map(size_t offset, size_t range)
+{
+  assert(mMappedPtr == nullptr && "Device memory must not be previously mapped!");
+  void *ptr = nullptr;
+  if (VkTestCall(mDevice.GetVkDevice()
+                        .mapMemory(mMemory, offset, range, vk::MemoryMapFlags(), &ptr)) !=
+      vk::Result::eSuccess)
+  {
+    return nullptr;
+  }
+  mMappedPtr = ptr;
+  return ptr;
+}
+
+void DeviceMemoryImpl::Unmap()
+{
+  assert(mMappedPtr != nullptr && "Device memory must be mapped!");
+  mDevice.GetVkDevice().unmapMemory(mMemory);
+  mMappedPtr = nullptr;
+}
+
+void DeviceMemoryImpl::Flush(size_t offset, size_t size)
+{
+  vk::MappedMemoryRange range;
+  range.setOffset(offset).setMemory(mMemory).setSize(size);
+  mDevice.GetVkDevice().flushMappedMemoryRanges(1, &range);
+}
+
+// Handle
+
+namespace
+{
+DeviceMemoryImpl* GetImpl(DeviceMemory* handle)
+{
+  return static_cast< DeviceMemoryImpl* >(handle->GetObject());
+}
+
+DeviceMemoryImpl* GetImpl(const DeviceMemory* handle)
+{
+  return static_cast< DeviceMemoryImpl* >(handle->GetObject());
+}
+}
+
+DeviceMemory DeviceMemory::New(class LogicalDevice& device, const vk::MemoryAllocateInfo& allocateInfo)
+{
+  auto impl = new DeviceMemoryImpl(device, allocateInfo);
+  if(impl->Initialise())
+  {
+    return impl;
+  }
+  return nullptr;
+}
+
+const LogicalDevice& DeviceMemory::GetLogicalDevice() const
+{
+  return GetImpl(this)->GetLogicalDevice();
+}
+
+const vk::DeviceMemory& DeviceMemory::GetVkDeviceMemory() const
+{
+  return GetImpl(this)->GetVkDeviceMemory();
+}
+
+const vk::DeviceMemory& DeviceMemory::operator*() const
+{
+  return GetImpl(this)->GetVkDeviceMemory();
+}
+
+size_t DeviceMemory::GetSize() const
+{
+  return GetImpl(this)->GetSize();
+}
+
+void* DeviceMemory::Map(size_t offset, size_t range)
+{
+  return GetImpl(this)->Map(offset, range);
+}
+
+void DeviceMemory::Unmap()
+{
+  GetImpl(this)->Unmap();
+}
+
+void DeviceMemory::Flush(size_t offset, size_t range)
+{
+  GetImpl(this)->Flush(offset, range);
+}
+
+void DeviceMemory::Flush()
+{
+  GetImpl(this)->Flush(0, VK_WHOLE_SIZE);
+}
+
+} // Vulkan
+} // Graphics
+} // Dali
diff --git a/dali/graphics/vulkan/device-memory.h b/dali/graphics/vulkan/device-memory.h
new file mode 100644 (file)
index 0000000..0688d9e
--- /dev/null
@@ -0,0 +1,81 @@
+#ifndef DALI_CORE_GRAPHICS_VULKAN_DEVICE_MEMORY_H
+#define DALI_CORE_GRAPHICS_VULKAN_DEVICE_MEMORY_H
+
+/*
+ * Copyright (c) 2017 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/graphics/vulkan/common.h>
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace Vulkan
+{
+
+class DeviceMemory : public VkHandle
+{
+public:
+  DeviceMemory(VkObject* object = nullptr) : VkHandle{object}
+  {
+  }
+
+  using VkHandle::operator=;
+
+  /**
+   * New DeviceMemory associated with logical device
+   * @param device
+   * @param allocateInfo
+   * @return
+   */
+  static DeviceMemory New(class LogicalDevice &device, const vk::MemoryAllocateInfo &allocateInfo);
+
+  /**
+   * Map memory ( only if host visible )
+   * @param offset
+   * @param range
+   * @return
+   */
+  void *Map(size_t offset, size_t range);
+
+  /**
+   * Unmap previously mapped memory
+   */
+  void Unmap();
+
+  /**
+   * Flush device memory in selected range
+   * @param offset
+   * @param range
+   */
+  void Flush(size_t offset, size_t range);
+
+  /**
+   * Flush entire block allocated as device memory
+   */
+  void Flush();
+
+  const class LogicalDevice &GetLogicalDevice() const;
+  const vk::DeviceMemory &   GetVkDeviceMemory() const;
+  const vk::DeviceMemory &operator*() const;
+  size_t GetSize() const;
+};
+}
+}
+}
+
+#endif // DALI_CORE_GRAPHICS_VULKAN_DEVICE_MEMORY_H
diff --git a/dali/graphics/vulkan/frame-stack.h b/dali/graphics/vulkan/frame-stack.h
new file mode 100644 (file)
index 0000000..dc2c65d
--- /dev/null
@@ -0,0 +1,124 @@
+#ifndef DALI_GRAPHICS_VULKAN_FRAME_STACK
+#define DALI_GRAPHICS_VULKAN_FRAME_STACK
+
+/*
+ * Copyright (c) 2017 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 <cstdint>
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace Vulkan
+{
+
+using Frame = char*;
+
+/**
+ * Simple stack frame-based fixed size allocator ( single sided )
+ */
+class Stack
+{
+public:
+
+  Stack( uint32_t capacityInBytes )
+  {
+    mData = new char[capacityInBytes];
+    mCurrentPtr = mData;
+    mCapacity = capacityInBytes;
+    mRecentFrame = nullptr;
+  }
+
+  ~Stack()
+  {
+    delete [] mCurrentPtr;
+  }
+
+  Frame Mark()
+  {
+    mRecentFrame = mCurrentPtr;
+    return mCurrentPtr;
+  }
+
+  Frame Rollback( Frame frame = nullptr )
+  {
+    if( !frame )
+    {
+      if( mRecentFrame )
+      {
+        mCurrentPtr  = mRecentFrame;
+        mRecentFrame = nullptr;
+      }
+      else
+      {
+        mCurrentPtr = mData;
+      }
+    }
+    return mCurrentPtr;
+  }
+
+  void RollbackAll()
+  {
+    mCurrentPtr = mData;
+  }
+
+  template <typename T>
+  T* Alloc( uint32_t count = 1 )
+  {
+    uintptr_t alignment = alignof(T)-(reinterpret_cast<uintptr_t>(mCurrentPtr)%alignof(T));
+    auto result = reinterpret_cast<T*>(mCurrentPtr + alignment);
+    if( result >= reinterpret_cast<T*>( mData + mCapacity ) )
+    {
+      return nullptr;
+    }
+    mCurrentPtr += sizeof(T) * count;
+    return result;
+  }
+
+  template <typename T, typename... Args>
+  T* AllocNew( Args&&... args )
+  {
+    T* ptr = Alloc<T>(1);
+    if(!ptr)
+    {
+      return nullptr;
+    }
+    return new(ptr)T(args...);
+  }
+
+  template <typename T, typename... Args>
+  T& AllocNewRef( Args&&... args )
+  {
+    T* ptr = Alloc<T>(1);
+    return *(new(ptr)T(args...));
+  }
+
+private:
+
+  char* mData { nullptr };
+  char* mCurrentPtr { nullptr };
+  char* mRecentFrame { nullptr };
+  uint32_t mCapacity { 0u };
+};
+
+} // namespace Vulkan
+} // namespace Graphics
+} // namespace Dali
+
+
+#endif //DALI_GRAPHICS_VULKAN_FRAME_STACK
diff --git a/dali/graphics/vulkan/framebuffer.cpp b/dali/graphics/vulkan/framebuffer.cpp
new file mode 100644 (file)
index 0000000..743059d
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2017 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 "framebuffer.h"
+#include <dali/graphics/vulkan/logical-device.h>
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace Vulkan
+{
+namespace Internal
+{
+class Framebuffer : public VkObject
+{
+public:
+  Framebuffer() = delete;
+
+  Framebuffer(const LogicalDevice &device, const vk::FramebufferCreateInfo &info)
+  : VkObject{}, mDevice{device}, mCreateInfo(info)
+  {
+  }
+
+  virtual ~Framebuffer() = default;
+
+  bool Initialise();
+
+  const vk::Framebuffer &GetVkObject() const
+  {
+    return mFramebuffer;
+  }
+
+  virtual bool OnSafeDelete() override
+  {
+    if( mFramebuffer )
+    {
+      mDevice->destroyFramebuffer(mFramebuffer, mDevice.GetVkAllocator());
+      return true;
+    }
+    return false;
+  }
+
+private:
+  LogicalDevice mDevice;
+
+  vk::FramebufferCreateInfo mCreateInfo {};
+  vk::Framebuffer mFramebuffer {nullptr};
+
+
+};
+
+bool Framebuffer::Initialise()
+{
+  return VkTestBool(mDevice->createFramebuffer(&mCreateInfo, mDevice.GetVkAllocator(), &mFramebuffer));
+}
+
+}
+
+namespace
+{
+Internal::Framebuffer* GetImpl( const Framebuffer* handle )
+{
+  return static_cast<Internal::Framebuffer*>(handle->GetObject());
+}
+
+}
+
+Framebuffer Framebuffer::New(const class LogicalDevice& device, const vk::FramebufferCreateInfo& info)
+{
+  auto impl = new Internal::Framebuffer(device, info);
+  if(impl->Initialise())
+  {
+    return impl;
+  }
+  return nullptr;
+}
+
+const vk::Framebuffer& Framebuffer::operator*() const
+{
+  return GetImpl(this)->GetVkObject();
+}
+
+}
+}
+}
\ No newline at end of file
diff --git a/dali/graphics/vulkan/framebuffer.h b/dali/graphics/vulkan/framebuffer.h
new file mode 100644 (file)
index 0000000..008210e
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef DALI_CORE_GRAPHICS_VULKAN_FRAMEBUFFER_H
+#define DALI_CORE_GRAPHICS_VULKAN_FRAMEBUFFER_H
+
+/*
+ * Copyright (c) 2017 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/graphics/vulkan/common.h>
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace Vulkan
+{
+
+class Framebuffer : public VkHandle
+{
+public:
+  OBJECT_HANDLE(Framebuffer)
+
+  const vk::Framebuffer& operator*() const;
+
+  static Framebuffer New( const class LogicalDevice& device, const vk::FramebufferCreateInfo& info );
+
+};
+
+}
+}
+}
+
+
+
+#endif //DALI_CORE_FRAMEBUFFER_H
diff --git a/dali/graphics/vulkan/image-view.cpp b/dali/graphics/vulkan/image-view.cpp
new file mode 100644 (file)
index 0000000..b449577
--- /dev/null
@@ -0,0 +1,37 @@
+//
+// Created by adam.b on 03/05/17.
+//
+
+#include <dali/graphics/vulkan/image-view.h>
+#include <dali/graphics/vulkan/image.h>
+namespace Dali
+{
+namespace Graphics
+{
+namespace Vulkan
+{
+namespace Internal
+{
+class ImageView : public VkObject
+{
+public:
+  ImageView() = delete;
+  ImageView( const Image& image, const vk::ImageViewCreateInfo& info );
+
+private:
+
+  Image mImage { nullptr };
+  vk::ImageViewCreateInfo mCreateInfo { };
+};
+
+ImageView::ImageView( const Image& image, const vk::ImageViewCreateInfo& info )
+: VkObject()
+{
+
+}
+
+}
+
+} // namespace Vulkan
+} // namespace Graphics
+} // namespace Dali
\ No newline at end of file
diff --git a/dali/graphics/vulkan/image-view.h b/dali/graphics/vulkan/image-view.h
new file mode 100644 (file)
index 0000000..8c8d6de
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2017 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.
+ *
+ */
+
+#ifndef DALI_CORE_GRAPHICS_VULKAN_IMAGEVIEW_H
+#define DALI_CORE_GRAPHICS_VULKAN_IMAGEVIEW_H
+
+#include <dali/graphics/vulkan/common.h>
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace Vulkan
+{
+
+class ImageView : public VkHandle
+{
+  OBJECT_HANDLE(ImageView)
+
+};
+
+} // namespace Vulkan
+} // namespace Graphics
+} // namespace Dali
+
+
+#endif //DALI_CORE_GRAPHICS_VULKAN_IMAGEVIEW_H
diff --git a/dali/graphics/vulkan/image.cpp b/dali/graphics/vulkan/image.cpp
new file mode 100644 (file)
index 0000000..ebc68c3
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2017 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/graphics/vulkan/device-memory.h>
+#include <dali/graphics/vulkan/image.h>
+#include <dali/graphics/vulkan/logical-device.h>
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace Vulkan
+{
+
+class ImageImpl : public VkObject
+{
+public:
+  ImageImpl(const LogicalDevice& device, const vk::ImageCreateInfo& createInfo);
+
+  /**
+   * Initialises new image
+   * @return
+   */
+  bool Initialise();
+
+  /**
+   * Creates VkImageMemoryBarrier instance in order to change image layout
+   * @param newLayout
+   * @param srcAccess
+   * @param dstAccess
+   * @return
+   */
+  vk::ImageMemoryBarrier CreateLayoutBarrier(vk::ImageLayout newLayout, vk::AccessFlags srcAccess,
+                                             vk::AccessFlags dstAccess);
+
+  const vk::Image& GetVkImage() const
+  {
+    return mImage;
+  }
+
+  bool BindDeviceMemory(const DeviceMemory& memory, size_t offset);
+
+  const vk::ImageCreateInfo& GetImageCreateInfo() const
+  {
+    return mCreateInfo;
+  }
+
+  const vk::ImageLayout& GetLayout() const
+  {
+    return mLayout;
+  }
+
+  void SetLayout(vk::ImageLayout layout )
+  {
+    mLayout = layout;
+  }
+
+private:
+  LogicalDevice       mDevice{nullptr};
+  vk::ImageCreateInfo mCreateInfo{};
+  vk::Image           mImage{nullptr};
+  vk::ImageLayout     mLayout;
+
+  DeviceMemory        mDeviceMemory{nullptr}; // todo future higher-level wrapper on device memory
+  size_t              mBoundMemoryOffset{0u};
+};
+
+// Implementation
+
+ImageImpl::ImageImpl(const LogicalDevice& device, const vk::ImageCreateInfo& createInfo)
+: mDevice(device), mCreateInfo(createInfo)
+{
+}
+
+bool ImageImpl::Initialise()
+{
+  mLayout = mCreateInfo.initialLayout;
+  return VkTestBool(mDevice->createImage(&mCreateInfo, mDevice.GetVkAllocator(), &mImage));
+}
+
+bool ImageImpl::BindDeviceMemory(const DeviceMemory& memory, size_t offset)
+{
+  assert(!mDeviceMemory && "DeviceMemory is already set on the Image!");
+  if( VkTestBool(mDevice->bindImageMemory(mImage, memory.GetVkDeviceMemory(), offset)) )
+  {
+    mDeviceMemory = memory;
+    mBoundMemoryOffset = offset;
+    return true;
+  }
+  return false;
+}
+
+vk::ImageMemoryBarrier ImageImpl::CreateLayoutBarrier(vk::ImageLayout newLayout,
+                                                      vk::AccessFlags srcAccess, vk::AccessFlags dstAccess)
+{
+  return vk::ImageMemoryBarrier{};
+}
+
+// Handle
+namespace
+{
+ImageImpl* GetImpl(Image* handle)
+{
+  return static_cast< ImageImpl* >(handle->GetObject());
+}
+ImageImpl* GetImpl(const Image* handle)
+{
+  return static_cast< ImageImpl* >(handle->GetObject());
+}
+}
+
+Image Image::New(const LogicalDevice& device, const vk::ImageCreateInfo& createInfo)
+{
+  auto impl = new ImageImpl(device, createInfo);
+  if(impl->Initialise())
+  {
+    return impl;
+  }
+  return nullptr;
+}
+
+const vk::Image& Image::GetVkResource() const
+{
+  return GetImpl(this)->GetVkImage();
+}
+
+const vk::Image& Image::operator*() const
+{
+  return GetImpl(this)->GetVkImage();
+}
+
+bool Image::BindDeviceMemory(const DeviceMemory& memory)
+{
+  return GetImpl(this)->BindDeviceMemory(memory, 0);
+}
+
+bool Image::BindDeviceMemory(const DeviceMemory& memory, size_t offset)
+{
+  return GetImpl(this)->BindDeviceMemory(memory, offset);
+}
+
+vk::ImageMemoryBarrier Image::GetLayoutChangeBarrier(vk::ImageLayout newLayout,
+                                                     vk::AccessFlags srcAccess, vk::AccessFlags dstAccess,
+                                                     vk::ImageAspectFlags imageAspect) const
+{
+  auto& info = GetImpl(this)->GetImageCreateInfo();
+
+  vk::ImageSubresourceRange subresourceRange;
+  subresourceRange.setBaseArrayLayer(0)
+      .setLayerCount(info.arrayLayers)
+      .setAspectMask(imageAspect)
+      .setBaseArrayLayer(0)
+      .setLevelCount(info.mipLevels)
+      .setBaseMipLevel(0);
+
+  vk::ImageMemoryBarrier barrier;
+  barrier.setNewLayout(newLayout)
+      .setOldLayout(GetImpl(this)->GetLayout())
+      .setSrcAccessMask(srcAccess)
+      .setDstAccessMask(dstAccess)
+      .setSubresourceRange(subresourceRange)
+      .setImage(GetImpl(this)->GetVkImage());
+
+  return barrier;
+}
+
+void Image::SetLayout( vk::ImageLayout layout )
+{
+  GetImpl(this)->SetLayout(layout);
+}
+
+vk::ImageLayout Image::GetLayout() const
+{
+  return GetImpl(this)->GetLayout();
+}
+}
+}
+}
diff --git a/dali/graphics/vulkan/image.h b/dali/graphics/vulkan/image.h
new file mode 100644 (file)
index 0000000..af98ec4
--- /dev/null
@@ -0,0 +1,62 @@
+#ifndef DALI_CORE_GRAPHICS_VULKAN_IMAGE_H
+#define DALI_CORE_GRAPHICS_VULKAN_IMAGE_H
+
+/*
+ * Copyright (c) 2017 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/graphics/vulkan/common.h>
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace Vulkan
+{
+
+class LogicalDevice;
+class DeviceMemory;
+
+class Image : public VkHandle
+{
+public:
+
+  Image(VkObject* impl = nullptr ) : VkHandle{impl}{}
+  using VkHandle::operator=;
+
+  static Image New( const LogicalDevice& device, const vk::ImageCreateInfo& createInfo );
+
+  const vk::Image& GetVkResource() const;
+  const vk::Image& operator*() const;
+
+  vk::ImageLayout GetLayout() const;
+  void SetLayout( vk::ImageLayout layout );
+  bool BindDeviceMemory( const class DeviceMemory& memory );
+  bool BindDeviceMemory( const class DeviceMemory& memory, size_t offset );
+
+  vk::ImageMemoryBarrier GetLayoutChangeBarrier( vk::ImageLayout newLayout, vk::AccessFlags srcAccess, vk::AccessFlags dstAccess, vk::ImageAspectFlags imageAspect ) const;
+
+private:
+
+};
+
+
+} // Vulkan
+} // Graphics
+} // Dali
+
+
+#endif // DALI_CORE_GRAPHICS_VULKAN_IMAGE_H
diff --git a/dali/graphics/vulkan/logical-device.cpp b/dali/graphics/vulkan/logical-device.cpp
new file mode 100644 (file)
index 0000000..263dac3
--- /dev/null
@@ -0,0 +1,320 @@
+/*
+ * Copyright (c) 2017 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/graphics/vulkan/command-queue.h>
+#include <dali/graphics/vulkan/frame-stack.h>
+#include <dali/graphics/vulkan/logical-device.h>
+#include <dali/graphics/vulkan/physical-device.h>
+#include <dali/graphics/vulkan/surface.h>
+#include <dali/graphics/vulkan/swapchain.h>
+namespace Dali
+{
+namespace Graphics
+{
+namespace Vulkan
+{
+
+using QueueArray       = std::vector< CommandQueue >;
+using FamilyQueueArray = std::vector< QueueArray >;
+
+class LogicalDeviceImpl : public GraphicsLogicalDeviceBase
+{
+public:
+  LogicalDeviceImpl(const PhysicalDevice &physicalDevice)
+  : GraphicsLogicalDeviceBase{}, mPhysicalDevice{physicalDevice}, mStack{1024}
+  {
+  }
+
+  const vk::Device &GetDevice() const
+  {
+    return mDevice;
+  }
+
+  const PhysicalDevice &GetPhysicalDevice() const
+  {
+    return mPhysicalDevice;
+  }
+
+  virtual bool Initialise() override;
+
+  virtual GraphicsSwapchain CreateSwapchain(const GraphicsSurface &surface,
+                                            uint32_t               bufferCount,
+                                            DepthStencil           depthStencil,
+                                            VSyncMode              enforceVSync) override;
+
+  virtual GraphicsPhysicalDevice GetGraphicsPhysicalDevice() const override
+  {
+    return GraphicsPhysicalDevice(mPhysicalDevice);
+  }
+
+  const CommandQueue &GetCommandQueue(uint32_t index, QueueType type) const;
+
+  vk::MemoryRequirements GetResourceMemoryRequirements(const vk::Image &image) const;
+
+  vk::MemoryRequirements GetResourceMemoryRequirements(const vk::Buffer &buffer) const;
+
+  uint32_t GetMemoryIndex(uint32_t memoryTypeBits, vk::MemoryPropertyFlags properties);
+
+  template< typename T >
+  DeviceMemory AllocateMemory(T object, vk::MemoryPropertyFlags flags, bool doBind);
+
+  Image CreateImage(vk::ImageCreateInfo info);
+
+  Stack &GetStack(uint32_t stackIndex)
+  {
+    return mStack;
+  }
+
+private:
+  vk::Device     mDevice{nullptr};
+  PhysicalDevice mPhysicalDevice;
+
+  ExtensionNameList          mEnabledExtensionCStr;
+  std::vector< std::string > mEnabledExtensionStr;
+  FamilyQueueArray           mQueueFamilyArray; // queues allocated per family
+  Stack                      mStack;
+  //VulkanCommandPool mTransientPool;
+};
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wframe-larger-than="
+bool LogicalDeviceImpl::Initialise()
+{
+  auto  physDevice = mPhysicalDevice.GetPhysicalDevice();
+  auto &features   = mPhysicalDevice.GetFeatures();
+  auto &stack      = GetStack(0);
+  stack.Mark();
+
+  // for each family allocate all possible queues when creating device
+  auto queueInfoArray = std::vector< vk::DeviceQueueCreateInfo >{};
+
+  // make a copy of used families and sort
+  auto familyIndices = std::vector< int >{};
+
+  auto newArray = std::vector< uint32_t >{mPhysicalDevice.GetQueueFamilyIndex(QueueType::GRAPHICS),
+                                          mPhysicalDevice.GetQueueFamilyIndex(QueueType::COMPUTE),
+                                          mPhysicalDevice.GetQueueFamilyIndex(QueueType::TRANSFER),
+                                          mPhysicalDevice.GetQueueFamilyIndex(QueueType::SPARSE_BINDING),
+                                          mPhysicalDevice.GetQueueFamilyIndex(QueueType::PRESENT)};
+
+  auto queueFamilyProperties = physDevice.getQueueFamilyProperties();
+
+  std::sort(newArray.begin(), newArray.end());
+
+  mQueueFamilyArray.resize(newArray.back() + 1);
+
+  uint32_t oldIndex   = -1u;
+  auto     priorities = std::vector< float >{};
+  for(auto &newIndex : newArray)
+  {
+    if(newIndex != oldIndex)
+    {
+      auto &familyProperties = queueFamilyProperties[newIndex];
+
+      // set priorities ( all queues have priority 1.0 to keep it simple )
+      priorities.resize(familyProperties.queueCount);
+      std::fill(priorities.begin(), priorities.end(), 1.0f);
+
+      // just resize arrays
+      mQueueFamilyArray[newIndex].resize(familyProperties.queueCount);
+
+      vk::DeviceQueueCreateInfo queueInfo;
+      queueInfo.setQueueCount(familyProperties.queueCount);
+      queueInfo.setQueueFamilyIndex(newIndex);
+      queueInfo.setPQueuePriorities(priorities.data());
+
+      queueInfoArray.emplace_back(queueInfo);
+
+      oldIndex = newIndex;
+    }
+  }
+
+  mEnabledExtensionCStr.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
+
+  auto deviceInfo = vk::DeviceCreateInfo{};
+  deviceInfo.setQueueCreateInfoCount(static_cast< uint32_t >(queueInfoArray.size()));
+  deviceInfo.setPQueueCreateInfos(queueInfoArray.data());
+  deviceInfo.setEnabledExtensionCount(static_cast< uint32_t >(mEnabledExtensionCStr.size()));
+  deviceInfo.setPpEnabledExtensionNames(mEnabledExtensionCStr.data());
+  deviceInfo.setPEnabledFeatures(&features);
+
+  VkAssertCall(physDevice.createDevice(&deviceInfo, mPhysicalDevice.GetAllocator(), &mDevice));
+
+  int familyIndex = 0;
+
+  // make a handle of the implementation
+  LogicalDevice logicalDevice(this);
+  for(auto &&family : mQueueFamilyArray)
+  {
+    for(uint32_t queueIndex = 0; queueIndex < family.size(); ++queueIndex)
+    {
+      family[queueIndex] = CommandQueue::Get(logicalDevice, static_cast< QueueType >(familyIndex), queueIndex);
+    }
+    ++familyIndex;
+  }
+
+  VkLog("[GraphicsPhysicalDevice] VkDevice created.");
+
+  return true;
+}
+#pragma GCC diagnostic pop
+
+GraphicsSwapchain LogicalDeviceImpl::CreateSwapchain(const GraphicsSurface &surface,
+                                                     uint32_t               bufferCount,
+                                                     DepthStencil           depthStencil,
+                                                     VSyncMode              enforceVSync)
+{
+  auto swapchain = Swapchain::New(LogicalDevice(this), Surface(surface.GetObject()), bufferCount, depthStencil);
+  swapchain.Initialise();
+  return swapchain;
+}
+
+const CommandQueue &LogicalDeviceImpl::GetCommandQueue(uint32_t index, QueueType type) const
+{
+  return mQueueFamilyArray[mPhysicalDevice.GetQueueFamilyIndex(type)][index];
+}
+
+vk::MemoryRequirements LogicalDeviceImpl::GetResourceMemoryRequirements(const vk::Image &image) const
+{
+  return mDevice.getImageMemoryRequirements(image);
+}
+
+vk::MemoryRequirements LogicalDeviceImpl::GetResourceMemoryRequirements(const vk::Buffer &buffer) const
+{
+  return mDevice.getBufferMemoryRequirements(buffer);
+}
+
+uint32_t LogicalDeviceImpl::GetMemoryIndex(uint32_t memoryTypeBits, vk::MemoryPropertyFlags properties)
+{
+  auto &memprops = mPhysicalDevice.GetMemoryProperties();
+  for(uint32_t i = 0; i < memprops.memoryTypeCount; ++i)
+  {
+    if((memoryTypeBits & (1u << i)) && ((memprops.memoryTypes[i].propertyFlags & properties) == properties))
+    {
+      return i;
+    }
+  }
+  return -1u;
+}
+
+template< typename T >
+DeviceMemory LogicalDeviceImpl::AllocateMemory(T object, vk::MemoryPropertyFlags flags, bool doBind)
+{
+  vk::MemoryRequirements req(GetResourceMemoryRequirements(*object));
+
+  vk::MemoryAllocateInfo info;
+  uint32_t               memoryIndex = GetMemoryIndex(req.memoryTypeBits, flags);
+  assert(memoryIndex != -1u && "Wrong memory index!");
+  info.setMemoryTypeIndex(memoryIndex).setAllocationSize(req.size);
+
+  LogicalDevice deviceHandle(this);
+  DeviceMemory  memory = DeviceMemory::New(deviceHandle, info);
+
+  if(doBind)
+  {
+    object.BindDeviceMemory(memory);
+  }
+
+  return memory;
+}
+
+Image LogicalDeviceImpl::CreateImage(vk::ImageCreateInfo info)
+{
+  return nullptr;
+}
+
+// End of implementation
+
+//
+
+namespace
+{
+LogicalDeviceImpl *GetImpl(const LogicalDevice *handle)
+{
+  return static_cast< LogicalDeviceImpl * >(handle->GetObject());
+}
+
+LogicalDeviceImpl *GetImpl(LogicalDevice *handle)
+{
+  return static_cast< LogicalDeviceImpl * >(handle->GetObject());
+}
+
+} //
+
+LogicalDevice LogicalDevice::New(const PhysicalDevice &physicalDevice)
+{
+  return LogicalDevice(new LogicalDeviceImpl(physicalDevice));
+}
+
+bool LogicalDevice::Initialise()
+{
+  return GetImpl(this)->Initialise();
+}
+
+const vk::Device *LogicalDevice::operator->() const
+{
+  auto &vkdevice = GetImpl(this)->GetDevice();
+  return &vkdevice;
+}
+
+DeviceMemory LogicalDevice::AllocateImageMemory(const Image &image, vk::MemoryPropertyFlags flags, bool doBind) const
+{
+  return GetImpl(this)->AllocateMemory(image, flags, doBind);
+}
+
+DeviceMemory LogicalDevice::AllocateBufferMemory(const Buffer &buffer, vk::MemoryPropertyFlags flags, bool doBind) const
+{
+  return GetImpl(this)->AllocateMemory(buffer, flags, doBind);
+}
+
+const vk::Device LogicalDevice::GetVkDevice() const
+{
+  return GetImpl(this)->GetDevice();
+}
+
+const PhysicalDevice &LogicalDevice::GetPhysicalDevice() const
+{
+  return GetImpl(this)->GetPhysicalDevice();
+}
+
+const vk::AllocationCallbacks *LogicalDevice::GetVkAllocator() const
+{
+  return GetImpl(this)->GetPhysicalDevice().GetAllocator();
+}
+
+CommandPool LogicalDevice::CreateCommandPool(QueueType type, bool createTransient, bool createResetCommandBuffer) const
+{
+  return CommandPool::New(*this, type, false, createTransient, createResetCommandBuffer);
+}
+
+const CommandQueue &LogicalDevice::GetCommandQueue(uint32_t index, QueueType type) const
+{
+  return GetImpl(this)->GetCommandQueue(index, type);
+}
+
+Image LogicalDevice::CreateImage(vk::ImageCreateInfo imageInfo)
+{
+  return GetImpl(this)->CreateImage(imageInfo);
+}
+
+Stack &LogicalDevice::GetStack(uint32_t stackIndex)
+{
+  return GetImpl(this)->GetStack(stackIndex);
+}
+}
+}
+}
diff --git a/dali/graphics/vulkan/logical-device.h b/dali/graphics/vulkan/logical-device.h
new file mode 100644 (file)
index 0000000..c4c6f2c
--- /dev/null
@@ -0,0 +1,119 @@
+#ifndef DALI_CORE_GRAPHICS_VULKAN_LOGICAL_DEVICE_H
+#define DALI_CORE_GRAPHICS_VULKAN_LOGICAL_DEVICE_H
+
+/*
+ * Copyright (c) 2017 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/graphics/graphics-logical-device.h>
+#include <dali/graphics/vulkan/buffer.h>
+#include <dali/graphics/vulkan/command-pool.h>
+#include <dali/graphics/vulkan/device-memory.h>
+#include <dali/graphics/vulkan/image.h>
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace Vulkan
+{
+class PhysicalDevice;
+class CommandQueue;
+class Stack;
+
+class LogicalDevice : public GraphicsLogicalDevice
+{
+public:
+  LogicalDevice(GraphicsLogicalDeviceBase* impl = nullptr) : GraphicsLogicalDevice{impl}
+  {
+  }
+
+  using GraphicsLogicalDevice::operator=;
+
+  bool Initialise();
+
+  const vk::Device GetVkDevice() const;
+
+  const vk::AllocationCallbacks* GetVkAllocator() const;
+
+  const PhysicalDevice& GetPhysicalDevice() const;
+
+  static LogicalDevice New(const PhysicalDevice& physicalDevice);
+
+  const vk::Device* operator->() const;
+
+  Stack& GetStack(uint32_t stackIndex);
+
+  /**
+   *
+   * @param image
+   * @param flags
+   * @param doBind
+   * @return
+   */
+  DeviceMemory AllocateImageMemory(const Image& image, vk::MemoryPropertyFlags flags, bool doBind) const;
+
+  /**
+   *
+   * @param buffer
+   * @param flags
+   * @param doBind
+   * @return
+   */
+  DeviceMemory AllocateBufferMemory(const Buffer& buffer, vk::MemoryPropertyFlags flags, bool doBind) const;
+
+  /**
+   * Creates new command pool with given settings
+   * @param type
+   * @param createTransient
+   * @param createResetCommandBuffer
+   * @return
+   */
+  CommandPool CreateCommandPool(QueueType type, bool createTransient, bool createResetCommandBuffer) const;
+
+  /**
+   * Returns one of the pre-allocated command queues or nullptr
+   * @param index
+   * @param type
+   * @return
+   */
+  const CommandQueue& GetCommandQueue(uint32_t index, QueueType type) const;
+
+  // Resources
+
+  /*
+   * IMAGE
+   */
+
+  /**
+   * Creates Vulkan image object
+   * @return
+   */
+  Image CreateImage2D(uint32_t width, uint32_t height, vk::Format pixelFormat, bool hostVisible, bool bindMemory);
+
+  /**
+   * Creates Vulkan Image from given VkImageCreateInfo structure
+   * @param imageInfo
+   * @return
+   */
+  Image CreateImage(vk::ImageCreateInfo imageInfo);
+};
+
+} // Vulkan
+} // Graphics
+} // Dali
+
+#endif //DALI_CORE_GRAPHICS_VULKAN_LOGICAL_DEVICE_H
diff --git a/dali/graphics/vulkan/physical-device.cpp b/dali/graphics/vulkan/physical-device.cpp
new file mode 100644 (file)
index 0000000..efb2257
--- /dev/null
@@ -0,0 +1,525 @@
+/*
+ * Copyright (c) 2017 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/graphics/vulkan/common.h>
+#include <dali/graphics/vulkan/logical-device.h>
+#include <dali/graphics/vulkan/physical-device.h>
+#include <dali/graphics/vulkan/surface.h>
+#include <dali/graphics/vulkan/surface/xcb-surface.h>
+#include <dali/graphics/vulkan/surface/xlib-surface.h>
+#include <cstdarg>
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace Vulkan
+{
+
+#define MAX_VKLOG_SIZE (1024 * 1024) // 1mb of log memory per thread
+__thread char* gLogBuffer = nullptr;
+
+// something to replace in the future, maybe
+void VkLog(const char* format, ...)
+{
+  if(!gLogBuffer)
+  {
+    gLogBuffer = new char[MAX_VKLOG_SIZE];
+  }
+  std::va_list args;
+  va_start(args, format);
+  vsnprintf(gLogBuffer, MAX_VKLOG_SIZE - 4, format, args);
+  puts(gLogBuffer);
+  va_end(args);
+}
+
+namespace
+{
+
+template< typename T >
+inline uint32_t Eval(const T& type)
+{
+  return static_cast< uint32_t >(type);
+}
+
+// debug callbacks
+#if VULKAN_USE_DEBUG_REPORT_CALLBACK
+VKAPI_ATTR VkBool32 VKAPI_CALL DebugReportCallback(VkDebugReportFlagsEXT      flags,
+                                                   VkDebugReportObjectTypeEXT objectType,
+                                                   uint64_t                   object,
+                                                   size_t                     location,
+                                                   int32_t                    messageCode,
+                                                   const char*                pLayerPrefix,
+                                                   const char*                pMessage,
+                                                   void*                      pUserData)
+{
+  VkLog("[VALIDATION:%s]: %s", pLayerPrefix, pMessage);
+  return VK_FALSE;
+}
+#endif
+const char* VALIDATION_LAYERS[] = {"VK_LAYER_LUNARG_screenshot",           // screenshot
+                                   "VK_LAYER_LUNARG_parameter_validation", // parameter
+                                   "VK_LAYER_LUNARG_vktrace", // vktrace ( requires vktrace connection )
+                                   "VK_LAYER_LUNARG_monitor",             // monitor
+                                   "VK_LAYER_LUNARG_swapchain",           // swapchain
+                                   "VK_LAYER_GOOGLE_threading",           // threading
+                                   "VK_LAYER_LUNARG_api_dump",            // api
+                                   "VK_LAYER_LUNARG_object_tracker",      // objects
+                                   "VK_LAYER_LUNARG_core_validation",     // core
+                                   "VK_LAYER_GOOGLE_unique_objects",      // unique objects
+                                   "VK_LAYER_LUNARG_standard_validation", // standard
+                                   nullptr};
+}
+
+/**
+ * Internal implementation of the Vulkan instance/physical device
+ */
+class PhysicalDeviceImpl : public Integration::GraphicsPhysicalDeviceBase
+{
+public:
+  //  GraphicsPhysicalDeviceBase
+public:
+  virtual bool Initialise(const ExtensionNameList& extensions, const ValidationLayerFlags2& layers);
+
+  virtual bool IsExtensionAvailable(const std::string& instanceExtensionName);
+
+  virtual bool IsLayerAvailable(const std::string& instanceExtensionName);
+
+  virtual GraphicsLogicalDevice CreateLogicalDevice(const ExtensionNameList& enabledExtensions);
+
+  virtual bool ChoosePhysicalDevice(const PhysicalDeviceFlags& flags);
+
+  virtual void SetValidationDebugChannels(const ValidationChannelFlags& flags)
+  {
+  }
+
+  virtual GraphicsSurface CreateSurface(const NativeSurfaceCreateInfo& info);
+
+  void PrepareQueueFamilies();
+
+  // Vulkan getters
+public:
+  vk::Instance GetInstance() const
+  {
+    return mVkInstance;
+  }
+
+  vk::PhysicalDevice GetPhysicalDevice() const
+  {
+    return mVkPhysicalDevice;
+  }
+
+  const vk::PhysicalDeviceFeatures& GetFeatures() const
+  {
+    return mPhysFeatures;
+  }
+
+  const vk::PhysicalDeviceProperties& GetProperties() const
+  {
+    return mPhysProperties;
+  }
+
+  const vk::PhysicalDeviceLimits& GetLimits() const
+  {
+    return mPhysLimits;
+  }
+
+  const vk::PhysicalDeviceMemoryProperties& GetMemoryProperties() const
+  {
+    return mPhysMemoryProperties;
+  }
+
+  const std::string& GetName() const
+  {
+    return mPhysName;
+  }
+
+  const std::string& GetVendorName() const
+  {
+    return mPhysVendorName;
+  }
+
+  const vk::AllocationCallbacks* GetAllocator() const
+  {
+    return mAllocatorCallbacks;
+  }
+
+  uint32_t GetQueueFamilyIndex(QueueType type) const
+  {
+    return mQueueFamilyIndex[Eval(type)];
+  }
+
+private:
+  // Vulkan instance extension properties list
+  std::vector< vk::ExtensionProperties > mInstanceExtensionProperties;
+
+  // Vulkan device extension properties list
+  std::vector< vk::ExtensionProperties > mDeviceExtensionProperties;
+
+  // Vulkan instance layer properties list
+  std::vector< vk::LayerProperties > mInstanceLayerProperties;
+
+  // Allocators
+  vk::AllocationCallbacks* mAllocatorCallbacks{nullptr};
+
+  // Instance
+  vk::Instance mVkInstance{nullptr};
+
+  // Physical device
+  vk::PhysicalDevice                 mVkPhysicalDevice{nullptr};
+  vk::PhysicalDeviceFeatures         mPhysFeatures{};
+  vk::PhysicalDeviceProperties       mPhysProperties{};
+  vk::PhysicalDeviceMemoryProperties mPhysMemoryProperties{};
+  vk::PhysicalDeviceType             mPhysType;
+  vk::PhysicalDeviceLimits           mPhysLimits;
+  uint32_t                           mPhysApiVersion{0};
+  uint32_t                           mPhysDriverVersion{0};
+  std::string                        mPhysName;
+  std::string                        mPhysVendorName;
+  bool                               mPhysIsDiscrete{false};
+
+  // Queue families
+  std::vector< vk::QueueFamilyProperties > mQueueFamilyProperties;
+  std::array< uint32_t, static_cast< uint32_t >(QueueType::END) > mQueueFamilyIndex;
+
+  // todo add surface type register
+};
+
+bool PhysicalDeviceImpl::IsExtensionAvailable(const std::string& instanceExtensionName)
+{
+  if(mInstanceExtensionProperties.empty())
+  {
+    auto result = vk::enumerateInstanceExtensionProperties();
+    if(result.result != vk::Result::eSuccess)
+    {
+      // todo no vulkan support????
+      return false;
+    }
+    mInstanceExtensionProperties = std::move(result.value);
+  }
+
+  for(auto&& ext : mInstanceExtensionProperties)
+  {
+    if(instanceExtensionName == ext.extensionName)
+    {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool PhysicalDeviceImpl::IsLayerAvailable(const std::string& instanceLayerName)
+{
+  if(mInstanceLayerProperties.empty())
+  {
+    auto result = vk::enumerateInstanceLayerProperties();
+    if(result.result != vk::Result::eSuccess)
+    {
+      // todo no vulkan support????
+      return false;
+    }
+    mInstanceLayerProperties = std::move(result.value);
+  }
+
+  for(auto&& ext : mInstanceLayerProperties)
+  {
+    if(instanceLayerName == ext.layerName)
+    {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool PhysicalDeviceImpl::Initialise(const ExtensionNameList& extensions, const ValidationLayerFlags2& layers)
+{
+  // make a copy and add debug report extension in case there are any
+  // validation layers listed
+  auto extCopy = ExtensionNameList{extensions};
+  if(layers != 0u)
+  {
+    extCopy.emplace_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
+  }
+
+  // add validation layers
+  LayerNameList layerTable;
+  auto          retval = LayerNameList{};
+
+  for(uint32_t bit = 0; VALIDATION_LAYERS[bit]; ++bit)
+  {
+    if(layers & (1u << bit))
+    {
+      layerTable.emplace_back(VALIDATION_LAYERS[bit]);
+    }
+  }
+
+  vk::InstanceCreateInfo info;
+  info.setEnabledExtensionCount(static_cast<uint32_t>(extCopy.size()))
+      .setPpEnabledExtensionNames(extCopy.data())
+      .setPApplicationInfo(nullptr)
+      .setPpEnabledLayerNames(layerTable.empty() ? nullptr : layerTable.data())
+      .setEnabledLayerCount(static_cast<uint32_t>(layerTable.size()));
+
+  return (vk::Result::eSuccess == VkTestCall(vk::createInstance(&info, mAllocatorCallbacks, &mVkInstance)));
+}
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wframe-larger-than="
+bool PhysicalDeviceImpl::ChoosePhysicalDevice(const PhysicalDeviceFlags& flags)
+{
+  auto preferredDiscrete = flags & PhysicalDeviceBit::DISCRETE ? true : false;
+
+  // set preferred device type
+  const vk::PhysicalDeviceType preferredType =
+      preferredDiscrete ? vk::PhysicalDeviceType::eDiscreteGpu : vk::PhysicalDeviceType::eIntegratedGpu;
+
+  // set fallback device type
+  const vk::PhysicalDeviceType fallbackType =
+      preferredDiscrete ? vk::PhysicalDeviceType::eIntegratedGpu : vk::PhysicalDeviceType::eDiscreteGpu;
+
+  auto result = mVkInstance.enumeratePhysicalDevices();
+  VkAssertCallMsg(result.result, "No Vulkan devices found!");
+
+  auto GPUs            = result.value;
+  auto currentGPU      = GPUs.front();
+  auto currentGPUProps = currentGPU.getProperties();
+
+  // select discreet over integrated
+  for(auto&& gpu : GPUs)
+  {
+    auto gpuProperties = gpu.getProperties();
+    if((currentGPUProps.deviceType != preferredType && gpuProperties.deviceType == preferredType) ||
+       (currentGPUProps.deviceType != preferredType && gpuProperties.deviceType == fallbackType))
+    {
+      currentGPU      = gpu;
+      currentGPUProps = gpuProperties;
+    }
+  }
+
+  // make sure selected GPU is THE REAL GPU not a blanket or refrigerator
+  if(currentGPUProps.deviceType != preferredType && currentGPUProps.deviceType != fallbackType)
+  {
+    // error
+    return false;
+  }
+
+  // store GPU data
+  // fixme
+  auto& gpu                 = currentGPU;
+  auto& gpuProperties       = currentGPUProps;
+  auto  gpuMemoryProperties = currentGPU.getMemoryProperties();
+  auto  gpuFeatures         = currentGPU.getFeatures();
+
+  auto deviceExtensionProperties = gpu.enumerateDeviceExtensionProperties();
+  mDeviceExtensionProperties     = deviceExtensionProperties.value;
+
+  auto queueFamilyProperties = gpu.getQueueFamilyProperties();
+
+  // collect all physical device related information
+  mPhysIsDiscrete       = preferredDiscrete;
+  mVkPhysicalDevice     = gpu;
+  mPhysProperties       = gpuProperties;
+  mPhysFeatures         = gpuFeatures;
+  mPhysMemoryProperties = gpuMemoryProperties;
+  mPhysLimits           = mPhysProperties.limits;
+  mPhysType             = mPhysProperties.deviceType;
+
+  // fill common stuff
+  mPhysName = mPhysProperties.deviceName;
+
+  switch(mPhysProperties.vendorID)
+  {
+  case 0x10DE: //nvidia
+    mPhysVendorName = "NVIDIA";
+    break;
+  default:
+    mPhysVendorName = "Unknown";
+  }
+
+  mPhysApiVersion    = mPhysProperties.apiVersion;
+  mPhysDriverVersion = mPhysProperties.driverVersion;
+
+  VkLog("[Vulkan] Found physical device: %s", mPhysName.c_str());
+  VkLog("[Vulkan]                vendor: %s", mPhysVendorName.c_str());
+
+  // prepare queue families
+  PrepareQueueFamilies();
+
+  return true;
+}
+#pragma GCC diagnostic pop
+
+GraphicsLogicalDevice PhysicalDeviceImpl::CreateLogicalDevice(const ExtensionNameList& enabledExtensions)
+{
+  LogicalDevice logicDevice(LogicalDevice::New(this));
+  if(!logicDevice.Initialise())
+  {
+    logicDevice = nullptr;
+  }
+  return logicDevice;
+}
+
+void PhysicalDeviceImpl::PrepareQueueFamilies()
+{
+  uint32_t& familyGraphics{mQueueFamilyIndex[Eval(QueueType::GRAPHICS)]};
+  uint32_t& familyTransfer{mQueueFamilyIndex[Eval(QueueType::TRANSFER)]};
+  uint32_t& familyCompute{mQueueFamilyIndex[Eval(QueueType::COMPUTE)]};
+  uint32_t& familySparseBinding{mQueueFamilyIndex[Eval(QueueType::SPARSE_BINDING)]};
+  uint32_t& familyPresent{mQueueFamilyIndex[Eval(QueueType::PRESENT)]};
+  familyGraphics = familyTransfer = familyCompute = familySparseBinding = familyPresent = -1u;
+
+  mQueueFamilyProperties = mVkPhysicalDevice.getQueueFamilyProperties();
+
+  uint32_t queueIndex = 0;
+  for(auto&& queueFamily : mQueueFamilyProperties)
+  {
+    if(familyGraphics == -1u && (queueFamily.queueFlags | vk::QueueFlagBits::eGraphics))
+    {
+      familyGraphics = queueIndex;
+    }
+    if(familyTransfer == -1u && (queueFamily.queueFlags | vk::QueueFlagBits::eTransfer))
+    {
+      familyTransfer = queueIndex;
+    }
+    if(familyCompute == -1u && (queueFamily.queueFlags | vk::QueueFlagBits::eCompute))
+    {
+      familyCompute = queueIndex;
+    }
+    if(familySparseBinding == -1u && (queueFamily.queueFlags | vk::QueueFlagBits::eSparseBinding))
+    {
+      familySparseBinding = queueIndex;
+    }
+
+    ++queueIndex;
+  }
+}
+
+GraphicsSurface PhysicalDeviceImpl::CreateSurface(const NativeSurfaceCreateInfo& info)
+{
+  uint32_t& familyPresent{mQueueFamilyIndex[Eval(QueueType::PRESENT)]};
+
+  assert(familyPresent == -1u && "Looks like the surface has been created!");
+
+  // should be part of adaptor????
+  GraphicsSurface retval{nullptr};
+  if(info.surfaceType == NativeSurfaceType::XCB)
+  {
+    const XcbSurfaceCreateInfo* xcbInfo = reinterpret_cast< const XcbSurfaceCreateInfo* >(&info);
+    GraphicsPhysicalDevice      physDevice(this);
+    retval = Surface::New< XcbSurface >(physDevice, xcbInfo->connection, xcbInfo->window);
+  }
+  else if(info.surfaceType == NativeSurfaceType::X11)
+  {
+    const XlibSurfaceCreateInfo* xlibInfo = reinterpret_cast< const XlibSurfaceCreateInfo* >(&info);
+    GraphicsPhysicalDevice       physDevice(this);
+    retval = Surface::New< XlibSurface >(physDevice, xlibInfo->display, xlibInfo->window);
+  }
+  // check surface compatibility against queue families
+  uint32_t queueIndex = 0;
+  for(size_t i = 0; i < mQueueFamilyProperties.size(); ++i)
+  {
+
+    // set present family upon surface creation
+    if(familyPresent == -1u)
+    {
+      vk::Bool32 supported{false};
+
+      mVkPhysicalDevice.getSurfaceSupportKHR(queueIndex, Surface(retval.GetObject()).GetSurface(), &supported);
+      if(supported)
+      {
+        familyPresent = queueIndex;
+        break;
+      }
+    }
+    ++queueIndex;
+  }
+
+  assert(familyPresent != -1u && "Surface not supported");
+
+  return retval;
+}
+
+/**************************************************************************
+ * Handle implementation
+ */
+
+PhysicalDeviceImpl* GetImpl(const PhysicalDevice* handle)
+{
+  return static_cast< PhysicalDeviceImpl* >(handle->GetObject());
+}
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wlarger-than="
+GraphicsPhysicalDevice PhysicalDevice::New()
+{
+  return GraphicsPhysicalDevice(new PhysicalDeviceImpl());
+}
+#pragma GCC diagnostic pop
+
+vk::Instance PhysicalDevice::GetInstance() const
+{
+  return GetImpl(this)->GetInstance();
+}
+
+vk::PhysicalDevice PhysicalDevice::GetPhysicalDevice() const
+{
+  return GetImpl(this)->GetPhysicalDevice();
+}
+
+const vk::PhysicalDeviceFeatures& PhysicalDevice::GetFeatures() const
+{
+  return GetImpl(this)->GetFeatures();
+}
+
+const vk::PhysicalDeviceProperties& PhysicalDevice::GetProperties() const
+{
+  return GetImpl(this)->GetProperties();
+}
+
+const vk::PhysicalDeviceLimits& PhysicalDevice::GetLimits() const
+{
+  return GetImpl(this)->GetLimits();
+}
+
+const vk::PhysicalDeviceMemoryProperties& PhysicalDevice::GetMemoryProperties() const
+{
+  return GetImpl(this)->GetMemoryProperties();
+}
+
+const std::string& PhysicalDevice::GetName() const
+{
+  return GetImpl(this)->GetName();
+}
+
+const std::string& PhysicalDevice::GetVendorName() const
+{
+  return GetImpl(this)->GetVendorName();
+}
+
+const vk::AllocationCallbacks* PhysicalDevice::GetAllocator() const
+{
+  return GetImpl(this)->GetAllocator();
+}
+
+uint32_t PhysicalDevice::GetQueueFamilyIndex(QueueType type) const
+{
+  return GetImpl(this)->GetQueueFamilyIndex(type);
+}
+
+} // Vulkan
+} // Graphics
+} // Dali
\ No newline at end of file
diff --git a/dali/graphics/vulkan/physical-device.h b/dali/graphics/vulkan/physical-device.h
new file mode 100644 (file)
index 0000000..c04c073
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef DALI_CORE_GRAPHICS_VULKAN_PHYSICAL_DEVICE_H
+#define DALI_CORE_GRAPHICS_VULKAN_PHYSICAL_DEVICE_H
+
+/*
+ * Copyright (c) 2017 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/graphics/graphics-physical-device.h>
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace Vulkan
+{
+class PhysicalDevice : public GraphicsPhysicalDevice
+{
+public:
+  PhysicalDevice(Integration::GraphicsPhysicalDeviceBase* impl = nullptr)
+  : GraphicsPhysicalDevice{impl}
+  {
+  }
+
+  using GraphicsPhysicalDevice::operator=;
+
+  // must not be virtual! ( for now )
+  static GraphicsPhysicalDevice New();
+
+  uint32_t GetQueueFamilyIndex(QueueType type) const;
+
+public:
+  // getters of bound Vulkan objects
+  vk::Instance                              GetInstance() const;
+  vk::PhysicalDevice                        GetPhysicalDevice() const;
+  const vk::AllocationCallbacks*            GetAllocator() const;
+  const vk::PhysicalDeviceFeatures&         GetFeatures() const;
+  const vk::PhysicalDeviceProperties&       GetProperties() const;
+  const vk::PhysicalDeviceLimits&           GetLimits() const;
+  const vk::PhysicalDeviceMemoryProperties& GetMemoryProperties() const;
+  const std::string&                        GetName() const;
+  const std::string&                        GetVendorName() const;
+};
+}
+}
+}
+
+#endif //DALI_CORE_GRAPHICS_VULKAN_PHYSICAL_DEVICE_H
diff --git a/dali/graphics/vulkan/surface.cpp b/dali/graphics/vulkan/surface.cpp
new file mode 100644 (file)
index 0000000..9a63a12
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2017 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/graphics/vulkan/surface.h>
+#include <dali/graphics/vulkan/surface/vulkan-surface-base.h>
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace Vulkan
+{
+
+
+uint32_t Surface::GetWidth() const
+{
+  return GetObject()->GetWidth();
+}
+
+uint32_t Surface::GetHeight() const
+{
+  return GetObject()->GetHeight();
+}
+
+const vk::SurfaceKHR Surface::GetSurface() const
+{
+  return static_cast<VulkanSurfaceBase*>(GetObject())->GetVkSurface();
+}
+
+const vk::SurfaceFormatKHR& Surface::GetFormat() const
+{
+  return static_cast<VulkanSurfaceBase*>(GetObject())->GetVkSurfaceFormat();
+}
+
+const vk::SurfaceCapabilitiesKHR& Surface::GetCapabilities() const
+{
+  return static_cast<VulkanSurfaceBase*>(GetObject())->GetCapabilities();
+}
+
+const std::vector< vk::SurfaceFormatKHR >& Surface::GetAllFormats() const
+{
+  return static_cast<VulkanSurfaceBase*>(GetObject())->GetAllFormats();
+}
+
+} // Vulkan
+} // Graphics
+} // Dali
diff --git a/dali/graphics/vulkan/surface.h b/dali/graphics/vulkan/surface.h
new file mode 100644 (file)
index 0000000..75d0832
--- /dev/null
@@ -0,0 +1,84 @@
+#ifndef DALI_CORE_GRAPHICS_VULKAN_SURFACE_H
+#define DALI_CORE_GRAPHICS_VULKAN_SURFACE_H
+
+/*
+ * Copyright (c) 2017 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/graphics/graphics-surface.h>
+#include <dali/graphics/vulkan/common.h>
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace Vulkan
+{
+/**
+ * This is a common handle for Vulkan surface implementation
+ */
+class Surface : public GraphicsSurface
+{
+public:
+  Surface(Integration::GraphicsSurfaceBase* impl = nullptr) : GraphicsSurface{impl}
+  {
+  }
+  using GraphicsSurface::operator=;
+
+  /**
+   * Returns surface width
+   * @return
+   */
+  uint32_t GetWidth() const;
+
+  /**
+ * Returns surface height
+ * @return
+ */
+  uint32_t GetHeight() const;
+
+  // Vulkan specific API
+public:
+  /**
+ * Returns associated Vulkan surface object
+ * @return
+ */
+  const vk::SurfaceKHR GetSurface() const;
+
+  /**
+   * Returns current surface format
+   * @return
+   */
+  const vk::SurfaceFormatKHR& GetFormat() const;
+
+  /**
+   *
+   * @return
+   */
+  const vk::SurfaceCapabilitiesKHR& GetCapabilities() const;
+
+  /**
+   * 
+   * @return
+   */
+  const std::vector< vk::SurfaceFormatKHR >& GetAllFormats() const;
+};
+
+} // Vulkan
+} // Graphics
+} // Dali
+
+#endif //DALI_CORE_GRAPHICS_VULKAN_SURFACE_H
diff --git a/dali/graphics/vulkan/surface/vulkan-surface-base.h b/dali/graphics/vulkan/surface/vulkan-surface-base.h
new file mode 100644 (file)
index 0000000..c2b2da7
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2017 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.
+ *
+ */
+
+#ifndef DALI_CORE_VULKAN_SURFACE_BASE_H
+#define DALI_CORE_VULKAN_SURFACE_BASE_H
+
+#include <dali/graphics/integration/graphics-surface-base.h>
+#include <dali/graphics/vulkan/common.h>
+
+namespace Dali
+{
+namespace Graphics
+{
+class GraphicsPhysicalDevice;
+
+namespace Vulkan
+{
+
+/**
+ * Internal interface inherited by the Surface implementation
+ */
+class VulkanSurfaceBase : public Integration::GraphicsSurfaceBase
+{
+public:
+  VulkanSurfaceBase(const GraphicsPhysicalDevice& physicalDevice)
+  : Integration::GraphicsSurfaceBase(physicalDevice){};
+  virtual ~VulkanSurfaceBase() = default;
+
+  virtual const vk::SurfaceKHR                       GetVkSurface() const       = 0;
+  virtual const vk::SurfaceFormatKHR&                GetVkSurfaceFormat() const = 0;
+  virtual const vk::SurfaceCapabilitiesKHR&          GetCapabilities() const    = 0;
+  virtual const std::vector< vk::SurfaceFormatKHR >& GetAllFormats() const      = 0;
+};
+}
+}
+}
+
+#endif //DALI_CORE_VULKAN_SURFACE_BASE_H
diff --git a/dali/graphics/vulkan/surface/xcb-surface.cpp b/dali/graphics/vulkan/surface/xcb-surface.cpp
new file mode 100644 (file)
index 0000000..3bef5c7
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2017 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/graphics/vulkan/physical-device.h>
+#include <dali/graphics/vulkan/surface/xcb-surface.h>
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace Vulkan
+{
+
+XcbSurface::XcbSurface(const GraphicsPhysicalDevice &device, xcb_connection_t *connection, xcb_window_t window)
+: VulkanSurfaceBase(device), mPhysicalDevice(device), mConnection(connection), mWindow(window)
+{
+}
+
+// GraphicsSurfaceBase
+
+bool XcbSurface::Initialise()
+{
+  xcb_generic_error_t *err;
+
+  PhysicalDevice device(mPhysicalDevice.GetObject());
+
+  auto cookie = xcb_get_geometry(mConnection, mWindow);
+  auto reply  = xcb_get_geometry_reply(mConnection, cookie, &err);
+
+  mSurfaceWidth  = reply->width;
+  mSurfaceHeight = reply->height;
+
+  auto vkInstance  = device.GetInstance();
+  auto vkAllocator = device.GetAllocator();
+  vk::XcbSurfaceCreateInfoKHR info;
+  info.setConnection(mConnection).setWindow(mWindow);
+
+  VkAssertCall(vkInstance.createXcbSurfaceKHR(&info, vkAllocator, &mSurface));
+
+  mFormats       = device.GetPhysicalDevice().getSurfaceFormatsKHR(mSurface).value;
+  mCapabilities  = device.GetPhysicalDevice().getSurfaceCapabilitiesKHR(mSurface).value;
+  mDefaultFormat = mFormats[0];
+  for(auto&& format : mFormats)
+  {
+    if(format.format == vk::Format::eR8G8B8A8Unorm)
+    {
+      mDefaultFormat = format;
+    }
+  }
+
+  return true;
+}
+
+bool XcbSurface::Replace()
+{
+  assert( true && "XcbSurface::Replace() not implemented!");
+  return false;
+}
+
+bool XcbSurface::Destroy()
+{
+  assert( true && "XcbSurface::Destroy() not implemented!");
+  return false;
+}
+
+uint32_t XcbSurface::GetWidth()
+{
+  return mSurfaceWidth;
+}
+
+uint32_t XcbSurface::GetHeight()
+{
+  return mSurfaceHeight;
+}
+
+// VulkanSurfaceBase
+
+const vk::SurfaceKHR XcbSurface::GetVkSurface() const
+{
+  return mSurface;
+}
+
+const vk::SurfaceFormatKHR& XcbSurface::GetVkSurfaceFormat() const
+{
+  return mDefaultFormat;
+}
+
+const vk::SurfaceCapabilitiesKHR& XcbSurface::GetCapabilities() const
+{
+  return mCapabilities;
+}
+
+const std::vector< vk::SurfaceFormatKHR >& XcbSurface::GetAllFormats() const
+{
+  return mFormats;
+}
+
+
+}
+}
+}
\ No newline at end of file
diff --git a/dali/graphics/vulkan/surface/xcb-surface.h b/dali/graphics/vulkan/surface/xcb-surface.h
new file mode 100644 (file)
index 0000000..9546388
--- /dev/null
@@ -0,0 +1,93 @@
+#ifndef DALI_CORE_GRAPHICS_VULKAN_XCB_SURFACE_H
+#define DALI_CORE_GRAPHICS_VULKAN_XCB_SURFACE_H
+
+/*
+ * Copyright (c) 2017 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/graphics/vulkan/surface/vulkan-surface-base.h>
+#include <xcb/xcb.h>
+#include <cinttypes>
+
+namespace Dali
+{
+namespace Graphics
+{
+class GraphicsPhysicalDevice;
+
+struct XcbSurfaceCreateInfo : NativeSurfaceCreateInfo
+{
+  XcbSurfaceCreateInfo() : NativeSurfaceCreateInfo(NativeSurfaceType::XCB)
+  {
+  }
+  xcb_connection_t* connection;
+  xcb_window_t      window;
+};
+
+namespace Vulkan
+{
+
+/**
+ * Implementation of Xcb surface
+ */
+class XcbSurface : public VulkanSurfaceBase
+{
+public:
+  XcbSurface(const GraphicsPhysicalDevice& adaptor, xcb_connection_t* connection, xcb_window_t window);
+
+  virtual ~XcbSurface() = default;
+
+  // GraphicsSurfaceBase
+
+  virtual bool Initialise();
+
+  virtual bool Replace();
+
+  virtual bool Destroy();
+
+  virtual uint32_t GetWidth();
+
+  virtual uint32_t GetHeight();
+
+  // VulkanSurfaceBase
+
+  virtual const vk::SurfaceKHR GetVkSurface() const;
+
+  virtual const vk::SurfaceFormatKHR& GetVkSurfaceFormat() const;
+
+  virtual const vk::SurfaceCapabilitiesKHR& GetCapabilities() const;
+
+  virtual const std::vector< vk::SurfaceFormatKHR >& GetAllFormats() const;
+
+private:
+  GraphicsPhysicalDevice mPhysicalDevice{nullptr};
+
+  vk::SurfaceKHR                      mSurface{nullptr};
+  vk::SurfaceCapabilitiesKHR          mCapabilities{};
+  vk::SurfaceFormatKHR                mDefaultFormat{};
+  std::vector< vk::SurfaceFormatKHR > mFormats{};
+
+  uint32_t mSurfaceWidth{0u};
+  uint32_t mSurfaceHeight{0u};
+
+  xcb_connection_t* mConnection{nullptr};
+  xcb_window_t      mWindow{};
+};
+}
+}
+}
+
+#endif //DALI_CORE_GRAPHICS_VULKAN_XCB_SURFACE_H
diff --git a/dali/graphics/vulkan/surface/xlib-surface.cpp b/dali/graphics/vulkan/surface/xlib-surface.cpp
new file mode 100644 (file)
index 0000000..b29f884
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2017 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/graphics/vulkan/physical-device.h>
+#include <dali/graphics/vulkan/surface/xlib-surface.h>
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace Vulkan
+{
+
+XlibSurface::XlibSurface(const GraphicsPhysicalDevice &device, Display* display, Window window)
+: VulkanSurfaceBase(device), mPhysicalDevice(device), mDisplay(display), mWindow(window)
+{
+}
+
+// GraphicsSurfaceBase
+
+bool XlibSurface::Initialise()
+{
+  PhysicalDevice device(mPhysicalDevice.GetObject());
+
+  Window root;
+  int x, y;
+  unsigned int width, height, borderWidth, depth;
+
+  XGetGeometry( mDisplay, mWindow, &root, &x, &y, &width, &height, &borderWidth, &depth );
+
+  mSurfaceWidth  = width;
+  mSurfaceHeight = height;
+
+  auto vkInstance  = device.GetInstance();
+  auto vkAllocator = device.GetAllocator();
+  vk::XlibSurfaceCreateInfoKHR info;
+  info.setWindow( mWindow );
+  info.setDpy( mDisplay );
+
+  VkAssertCall(vkInstance.createXlibSurfaceKHR(&info, vkAllocator, &mSurface));
+
+  mFormats       = device.GetPhysicalDevice().getSurfaceFormatsKHR(mSurface).value;
+  mCapabilities  = device.GetPhysicalDevice().getSurfaceCapabilitiesKHR(mSurface).value;
+  mDefaultFormat = mFormats[0];
+  for(auto&& format : mFormats)
+  {
+    if(format.format == vk::Format::eR8G8B8A8Unorm)
+    {
+      mDefaultFormat = format;
+    }
+  }
+
+  return true;
+}
+
+bool XlibSurface::Replace()
+{
+  assert( "XcbSurface::Replace() not implemented!");
+  return false;
+}
+
+bool XlibSurface::Destroy()
+{
+  assert( "XcbSurface::Destroy() not implemented!");
+  return false;
+}
+
+uint32_t XlibSurface::GetWidth()
+{
+  return mSurfaceWidth;
+}
+
+uint32_t XlibSurface::GetHeight()
+{
+  return mSurfaceHeight;
+}
+
+// VulkanSurfaceBase
+
+const vk::SurfaceKHR XlibSurface::GetVkSurface() const
+{
+  return mSurface;
+}
+
+const vk::SurfaceFormatKHR& XlibSurface::GetVkSurfaceFormat() const
+{
+  return mDefaultFormat;
+}
+
+const vk::SurfaceCapabilitiesKHR& XlibSurface::GetCapabilities() const
+{
+  return mCapabilities;
+}
+
+const std::vector< vk::SurfaceFormatKHR >& XlibSurface::GetAllFormats() const
+{
+  return mFormats;
+}
+
+
+}
+}
+}
\ No newline at end of file
diff --git a/dali/graphics/vulkan/surface/xlib-surface.h b/dali/graphics/vulkan/surface/xlib-surface.h
new file mode 100644 (file)
index 0000000..c70c282
--- /dev/null
@@ -0,0 +1,93 @@
+#ifndef DALI_CORE_GRAPHICS_VULKAN_XLIB_SURFACE_H
+#define DALI_CORE_GRAPHICS_VULKAN_XLIB_SURFACE_H
+
+/*
+ * Copyright (c) 2017 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 <X11/Xlib.h>
+#include <dali/graphics/vulkan/surface/vulkan-surface-base.h>
+#include <cinttypes>
+
+namespace Dali
+{
+namespace Graphics
+{
+class GraphicsPhysicalDevice;
+
+struct XlibSurfaceCreateInfo : NativeSurfaceCreateInfo
+{
+  XlibSurfaceCreateInfo() : NativeSurfaceCreateInfo(NativeSurfaceType::X11)
+  {
+  }
+  Display* display;
+  Window   window;
+};
+
+namespace Vulkan
+{
+
+/**
+ * Implementation of Xlib surface
+ */
+class XlibSurface : public VulkanSurfaceBase
+{
+public:
+  XlibSurface(const GraphicsPhysicalDevice& device, Display* display, Window window);
+
+  virtual ~XlibSurface() = default;
+
+  // GraphicsSurfaceBase
+
+  virtual bool Initialise();
+
+  virtual bool Replace();
+
+  virtual bool Destroy();
+
+  virtual uint32_t GetWidth();
+
+  virtual uint32_t GetHeight();
+
+  // VulkanSurfaceBase
+
+  virtual const vk::SurfaceKHR GetVkSurface() const;
+
+  virtual const vk::SurfaceFormatKHR& GetVkSurfaceFormat() const;
+
+  virtual const vk::SurfaceCapabilitiesKHR& GetCapabilities() const;
+
+  virtual const std::vector< vk::SurfaceFormatKHR >& GetAllFormats() const;
+
+private:
+  GraphicsPhysicalDevice mPhysicalDevice{nullptr};
+
+  vk::SurfaceKHR                      mSurface{nullptr};
+  vk::SurfaceCapabilitiesKHR          mCapabilities{};
+  vk::SurfaceFormatKHR                mDefaultFormat{};
+  std::vector< vk::SurfaceFormatKHR > mFormats{};
+
+  uint32_t mSurfaceWidth{0u};
+  uint32_t mSurfaceHeight{0u};
+
+  Display* mDisplay{nullptr};
+  Window   mWindow{};
+};
+}
+}
+}
+
+#endif //DALI_CORE_GRAPHICS_VULKAN_XLIB_SURFACE_H
diff --git a/dali/graphics/vulkan/swapchain.cpp b/dali/graphics/vulkan/swapchain.cpp
new file mode 100644 (file)
index 0000000..1d31251
--- /dev/null
@@ -0,0 +1,720 @@
+/*
+ * Copyright (c) 2017 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/graphics/vulkan/command-buffer.h>
+#include <dali/graphics/vulkan/command-pool.h>
+#include <dali/graphics/vulkan/command-queue.h>
+#include <dali/graphics/vulkan/device-memory.h>
+#include <dali/graphics/vulkan/frame-stack.h>
+#include <dali/graphics/vulkan/image.h>
+#include <dali/graphics/vulkan/logical-device.h>
+#include <dali/graphics/vulkan/surface.h>
+#include <dali/graphics/vulkan/swapchain.h>
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace Vulkan
+{
+
+struct SwapchainFramebuffer
+{
+  vk::Framebuffer framebuffer{nullptr};
+
+  vk::Image       image{nullptr};
+  vk::ImageView   imageView{nullptr};
+  vk::ImageLayout layout{vk::ImageLayout::eUndefined};
+
+  CommandBuffer commandBuffer;
+  bool          submitted{false};
+  vk::Fence     fence{nullptr};
+};
+
+using SwapchainBufferArray = std::vector< SwapchainFramebuffer >;
+
+// swapchain implementation
+class SwapchainImpl : public Integration::GraphicsSwapchainBase
+{
+public:
+  SwapchainImpl(const LogicalDevice& device, const Vulkan::Surface& surface, uint32_t bufferCount,
+                DepthStencil depthStencil);
+  virtual ~SwapchainImpl() = default;
+
+  /**
+   * Presents frame
+   * @param queue
+   */
+  void Present(const CommandQueue& queue);
+
+  /**
+   *
+   */
+  void Present();
+
+  /**
+   * Begins new frame
+   */
+  void BeginFrame();
+
+  /**
+   * Replace swapchain
+   */
+  void Replace();
+
+  /**
+   * Creates optional depth/stencil buffer
+   */
+  void CreateDepthStencil();
+
+  /**
+   * Obtains swapchain images
+   */
+  void GetSwapchainImages();
+
+  /**
+   * Creates main render pass used by swapchain
+   */
+  void CreateMainRenderPass();
+
+  /**
+   * Creates main commandbuffers related to the swapchain
+   */
+  void CreateCommandBuffers();
+
+  /**
+   * Creates necessary semaphores
+   */
+  void CreateSemaphores();
+
+  /**
+   *
+   * @param index
+   * @return
+   */
+  const CommandBuffer& GetCommandBuffer(uint32_t index) const
+  {
+    return mBuffers[index].commandBuffer;
+  }
+
+  /**
+   *
+   * @return
+   */
+  const CommandBuffer& GetCurrentCommandBuffer() const
+  {
+    return mBuffers[mAcquiredBufferIndex].commandBuffer;
+  }
+
+  const vk::Image& GetCurrentImage() const
+  {
+    return mBuffers[mAcquiredBufferIndex].image;
+  }
+
+  // swapchain integration
+public:
+  virtual bool Initialise();
+
+  virtual bool AcquireFrame();
+
+  virtual bool PresentFrame();
+
+private:
+  void GenerateViewFramebuffer(uint32_t bufferIndex, const vk::Image& image);
+
+  void BeginRenderPass(CommandBuffer& cmdbuf);
+  void RecordDepthStencilBarrier(vk::ImageMemoryBarrier& barrier);
+  void RecordColorBarrier(vk::ImageMemoryBarrier& barrier, SwapchainFramebuffer& swapbuffer);
+  void AcquireNextImage();
+
+  vk::SwapchainKHR mVkSwapchain{nullptr};
+  vk::SwapchainKHR mVkOldSwapchain{nullptr};
+
+  // Depth/stencil
+  Image         mVkDepthStencilImage{nullptr};
+  vk::ImageView mVkDepthStencilImageView{nullptr};
+  DeviceMemory  mVkDepthStencilImageMemory{nullptr};
+  vk::Format    mDepthStencilFormat{};
+  bool          mDepthStencilLayoutChangeNeeded{false}; // this flag indicates whether with new frame it's also necessary to change image layout (done once only)
+
+  // renderpass
+  vk::RenderPass mRenderPass{nullptr};
+
+  LogicalDevice mDevice;
+
+  Surface mSurface;
+
+  SwapchainBufferArray mBuffers{};
+
+  std::vector< vk::Semaphore > mAcquireSemaphore; // array of semaphores, can't be placed inside the buffer as
+                                                  // we don't know the first index
+  std::vector< vk::Semaphore > mPresentSemaphore;
+
+  CommandPool mCommandPool{nullptr}; // command pool
+
+  uint32_t     mCurrentBufferIndex{0};
+  uint32_t     mAcquiredBufferIndex{-1u};
+  uint32_t     mMaxBufferCount{-1u};
+  DepthStencil mDepthStencilMode;
+};
+
+SwapchainImpl::SwapchainImpl(const LogicalDevice& device, const Vulkan::Surface& surface,
+                             uint32_t bufferCount, DepthStencil depthStencil)
+: GraphicsSwapchainBase(), mDevice(device), mSurface{surface}, mMaxBufferCount(bufferCount), mDepthStencilMode(depthStencil)
+{
+}
+
+bool SwapchainImpl::Initialise()
+{
+  // create new command pool for new swapchain
+  if(!mCommandPool)
+  {
+    mCommandPool = mDevice.CreateCommandPool(QueueType::GRAPHICS, false, false);
+  }
+  // just replace swapchain
+  Replace();
+  return true;
+}
+
+bool SwapchainImpl::AcquireFrame()
+{
+  BeginFrame();
+  return true;
+}
+
+bool SwapchainImpl::PresentFrame()
+{
+  Present();
+  return true;
+}
+
+/**
+ * Replacing surface makes sure all device operations completed as new surface will bring a
+ * new image resources etc.
+ */
+void SwapchainImpl::Replace()
+{
+
+  // wait for device to finish
+  if(mVkSwapchain)
+  {
+    // Todo: make sure no other part of implementation is executing on other threads
+    // This situation is very rare so vkDeviceWaitIdle() won't hurt performance
+    mDevice.GetVkDevice().waitIdle();
+
+    mVkOldSwapchain = mVkSwapchain;
+    mVkSwapchain    = nullptr;
+
+    // todo: if size of surface changed the depth may need to be recreated
+    // vkDestroyImageView()
+    // vkDestroyImage()
+  }
+
+  vk::SwapchainCreateInfoKHR info;
+  info.setSurface(mSurface.GetSurface())
+      .setQueueFamilyIndexCount(0)
+      .setPQueueFamilyIndices(nullptr)
+      .setPreTransform(vk::SurfaceTransformFlagBitsKHR::eIdentity)
+      .setPresentMode(vk::PresentModeKHR::eFifo)
+      .setOldSwapchain(mVkOldSwapchain)
+      .setMinImageCount(mMaxBufferCount)
+      .setImageUsage(vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferDst)
+      .setImageSharingMode(vk::SharingMode::eExclusive)
+      .setImageExtent({mSurface.GetWidth(), mSurface.GetHeight()})
+      .setImageFormat(mSurface.GetFormat().format)
+      .setImageColorSpace(mSurface.GetFormat().colorSpace)
+      .setCompositeAlpha(vk::CompositeAlphaFlagBitsKHR::eOpaque)
+      .setImageArrayLayers(1)
+      .setClipped(true);
+
+  VkAssertCall(mDevice.GetVkDevice().createSwapchainKHR(&info, mDevice.GetVkAllocator(), &mVkSwapchain));
+
+  CreateMainRenderPass();
+
+  // create depth stencil buffer
+  CreateDepthStencil();
+
+  // extract images ( no need to delete existing ones except of views )
+  GetSwapchainImages();
+
+  // Create semaphores ( 2 per buffer );
+  CreateSemaphores();
+
+  // create command buffers ( won't do anything if buffers are already allocated )
+  // fixme: it might not be a good idea to reuse previous buffers
+  CreateCommandBuffers();
+
+  mCurrentBufferIndex = 0;
+}
+
+void SwapchainImpl::CreateDepthStencil()
+{
+  if(mDepthStencilMode == DepthStencil::NONE)
+  {
+    return;
+  }
+
+  // free any existing depth buffer
+  if(mVkDepthStencilImageView)
+  {
+    mDevice.GetVkDevice().destroyImageView(mVkDepthStencilImageView, mDevice.GetVkAllocator());
+  }
+  if(mVkDepthStencilImage)
+  {
+    //mDevice.GetVkDevice().destroyImage(mVkDepthStencilImage, mDevice.GetVkAllocator());
+    mVkDepthStencilImage = nullptr;
+  }
+
+  // todo: include the proper depth stencil settings
+  vk::Format format   = vk::Format::eD16Unorm;
+  mDepthStencilFormat = format;
+
+  Stack stack(1024);
+
+  auto& imageInfo     = *stack.AllocNew< vk::ImageCreateInfo >();
+  auto& imageViewInfo = *stack.AllocNew< vk::ImageViewCreateInfo >();
+
+  imageInfo.setPQueueFamilyIndices(nullptr)
+      .setQueueFamilyIndexCount(0)
+      .setSamples(vk::SampleCountFlagBits::e1)
+      .setInitialLayout(vk::ImageLayout::eUndefined)
+      .setArrayLayers(1)
+      .setExtent({mSurface.GetWidth(), mSurface.GetHeight(), 1})
+      .setImageType(vk::ImageType::e2D)
+      .setMipLevels(1)
+      .setSharingMode(vk::SharingMode::eExclusive)
+      .setTiling(vk::ImageTiling::eOptimal)
+      .setFormat(format)
+      .setUsage(vk::ImageUsageFlagBits::eDepthStencilAttachment);
+
+  // create image
+  mVkDepthStencilImage = Image::New(mDevice, imageInfo);
+
+  imageViewInfo.setFormat(format)
+      .setSubresourceRange(vk::ImageSubresourceRange()
+                               .setLayerCount(1)
+                               .setBaseArrayLayer(0)
+                               .setBaseMipLevel(0)
+                               .setLevelCount(1)
+                               .setLayerCount(1)
+                               .setAspectMask(vk::ImageAspectFlagBits::eDepth))
+      .setImage(*mVkDepthStencilImage)
+      .setViewType(vk::ImageViewType::e2D)
+      .setComponents(vk::ComponentMapping()
+                         .setR(vk::ComponentSwizzle::eR)
+                         .setG(vk::ComponentSwizzle::eG)
+                         .setB(vk::ComponentSwizzle::eB)
+                         .setA(vk::ComponentSwizzle::eA));
+
+  // create view
+  VkAssertCall(mDevice.GetVkDevice().createImageView(&imageViewInfo, mDevice.GetVkAllocator(),
+                                                     &mVkDepthStencilImageView));
+
+  // allocate memory
+  mVkDepthStencilImageMemory =
+      mDevice.AllocateImageMemory(mVkDepthStencilImage, vk::MemoryPropertyFlagBits::eDeviceLocal, false);
+  mVkDepthStencilImage.BindDeviceMemory(mVkDepthStencilImageMemory);
+
+  // request changing layout with next frame
+  mDepthStencilLayoutChangeNeeded = true;
+}
+
+void SwapchainImpl::GetSwapchainImages()
+{
+  auto device = mDevice.GetVkDevice();
+  if(!mBuffers.empty())
+  {
+    // delete only views, images are discarded by swapchain as swapchain bound resource
+    // we do not discard existing command buffers, no need when replacing swapchain
+    for(auto&& buffer : mBuffers)
+    {
+      device.destroyImageView(buffer.imageView, mDevice.GetVkAllocator());
+      device.destroyFramebuffer(buffer.framebuffer, mDevice.GetVkAllocator());
+      buffer.imageView   = nullptr;
+      buffer.framebuffer = nullptr;
+    }
+  }
+
+  // obtain images
+  auto images = device.getSwapchainImagesKHR(mVkSwapchain).value;
+  assert(images.size() == mMaxBufferCount);
+
+  if(mBuffers.empty())
+  {
+    mBuffers.resize(images.size());
+  }
+
+  // generate views and framebuffers
+  for(uint32_t i = 0; i < mBuffers.size(); ++i)
+  {
+    GenerateViewFramebuffer(i, images[i]);
+  }
+}
+
+void SwapchainImpl::GenerateViewFramebuffer(uint32_t bufferIndex, const vk::Image& image)
+{
+  Stack stack(1024);
+  auto& ivInfo      = *stack.AllocNew< vk::ImageViewCreateInfo >();
+  ivInfo.components = (*stack.AllocNew< vk::ComponentMapping >())
+                          .setR(vk::ComponentSwizzle::eR)
+                          .setG(vk::ComponentSwizzle::eG)
+                          .setB(vk::ComponentSwizzle::eB)
+                          .setA(vk::ComponentSwizzle::eA);
+  ivInfo.viewType         = vk::ImageViewType::e2D;
+  ivInfo.image            = image;
+  ivInfo.subresourceRange = (*stack.AllocNew< vk::ImageSubresourceRange >())
+                                .setLayerCount(1)
+                                .setBaseArrayLayer(0)
+                                .setBaseMipLevel(0)
+                                .setLevelCount(1)
+                                .setLayerCount(1)
+                                .setAspectMask(vk::ImageAspectFlagBits::eColor);
+  ivInfo.setFormat(mSurface.GetFormat().format);
+
+  auto& fbInfo = *stack.AllocNew< vk::FramebufferCreateInfo >();
+
+  fbInfo.pAttachments    = nullptr;
+  fbInfo.attachmentCount = mDepthStencilMode != DepthStencil::NONE ? 2 : 1;
+  fbInfo.renderPass      = mRenderPass;
+  fbInfo.layers          = 1;
+  fbInfo.width           = mSurface.GetWidth();
+  fbInfo.height          = mSurface.GetHeight();
+
+  auto& buffer = mBuffers[bufferIndex];
+
+  // create image view
+  buffer.image = image;
+  ivInfo.setImage(buffer.image);
+  VkAssertCall(mDevice.GetVkDevice().createImageView(&ivInfo, mDevice.GetVkAllocator(), &buffer.imageView));
+
+  auto attachments = stack.Alloc< vk::ImageView >(2);
+  attachments[0]   = buffer.imageView;
+  attachments[1]   = mVkDepthStencilImageView;
+
+  // create framebuffer
+  fbInfo.pAttachments = attachments;
+  VkAssertCall(mDevice.GetVkDevice().createFramebuffer(&fbInfo, mDevice.GetVkAllocator(), &buffer.framebuffer));
+  buffer.layout = vk::ImageLayout::eUndefined;
+}
+
+void SwapchainImpl::CreateMainRenderPass()
+{
+  // Todo: sampling
+  // Todo: stencil
+  // Todo: separate clear if not needed ( however it's better if render pass does clear framebuffer automatically )
+  auto device    = mDevice.GetVkDevice();
+  auto allocator = mDevice.GetVkAllocator();
+
+  auto stack = Stack{1024};
+
+  uint32_t attCount = mDepthStencilMode != DepthStencil::NONE ? 2 : 1;
+
+  vk::AttachmentReference attRef[2] = {
+      vk::AttachmentReference().setLayout(vk::ImageLayout::eColorAttachmentOptimal).setAttachment(0),
+      vk::AttachmentReference().setLayout(vk::ImageLayout::eDepthStencilAttachmentOptimal).setAttachment(1)};
+
+  auto& subpassDescription = *stack.AllocNew< vk::SubpassDescription >();
+  subpassDescription.setPResolveAttachments(nullptr)
+      .setPipelineBindPoint(vk::PipelineBindPoint::eGraphics)
+      .setPDepthStencilAttachment(attCount == 2 ? &attRef[1] : nullptr)
+      .setPColorAttachments(&attRef[0])
+      .setColorAttachmentCount(1);
+
+  auto attDesc = stack.Alloc< vk::AttachmentDescription >(2);
+  attDesc[0]   = vk::AttachmentDescription()
+                   .setFormat(mSurface.GetFormat().format)
+                   .setInitialLayout(vk::ImageLayout::eColorAttachmentOptimal)
+                   .setSamples(vk::SampleCountFlagBits::e1)
+                   .setStoreOp(vk::AttachmentStoreOp::eStore)
+                   .setStencilLoadOp(vk::AttachmentLoadOp::eClear)
+                   .setLoadOp(vk::AttachmentLoadOp::eClear)
+                   .setFinalLayout(vk::ImageLayout::ePresentSrcKHR);
+  attDesc[1] = vk::AttachmentDescription()
+                   .setFormat(mDepthStencilFormat)
+                   .setInitialLayout(vk::ImageLayout::eDepthStencilAttachmentOptimal)
+                   .setSamples(vk::SampleCountFlagBits::e1)
+                   .setStoreOp(vk::AttachmentStoreOp::eDontCare)
+                   .setStencilLoadOp(vk::AttachmentLoadOp::eClear)
+                   .setLoadOp(vk::AttachmentLoadOp::eClear)
+                   .setFinalLayout(vk::ImageLayout::eDepthStencilAttachmentOptimal);
+
+  auto& rpInfo = stack.AllocNewRef< vk::RenderPassCreateInfo >();
+  rpInfo.setSubpassCount(1).setPSubpasses(&subpassDescription).setAttachmentCount(attCount).setPAttachments(attDesc);
+
+  VkAssertCall(device.createRenderPass(&rpInfo, allocator, &mRenderPass));
+}
+
+void SwapchainImpl::CreateCommandBuffers()
+{
+  auto device = mDevice.GetVkDevice();
+  for(auto&& buffer : mBuffers)
+  {
+    // create command buffer
+    if(!buffer.commandBuffer)
+    {
+      buffer.commandBuffer = mCommandPool.AllocateCommandBuffer(true);
+    }
+
+    // create fence
+    if(!buffer.fence)
+    {
+      vk::FenceCreateInfo info;
+      VkAssertCall(device.createFence(&info, mDevice.GetVkAllocator(), &buffer.fence));
+    }
+  }
+}
+
+void SwapchainImpl::CreateSemaphores()
+{
+  auto device = mDevice.GetVkDevice();
+  if(mAcquireSemaphore.empty())
+  {
+    mAcquireSemaphore.resize(mMaxBufferCount + 1);
+  }
+  if(mPresentSemaphore.empty())
+  {
+    mPresentSemaphore.resize(mMaxBufferCount + 1);
+  }
+
+  vk::SemaphoreCreateInfo info;
+  for(auto&& sem : mAcquireSemaphore)
+  {
+    if(!sem)
+    {
+      VkAssertCall(device.createSemaphore(&info, mDevice.GetVkAllocator(), &sem));
+    }
+  }
+  for(auto&& sem : mPresentSemaphore)
+  {
+    if(!sem)
+    {
+      VkAssertCall(device.createSemaphore(&info, mDevice.GetVkAllocator(), &sem));
+    }
+  }
+}
+
+void SwapchainImpl::BeginFrame()
+{
+  auto& stack = mDevice.GetStack(0);
+  auto  frame = stack.Mark();
+
+  auto& swapbuffer = mBuffers[mAcquiredBufferIndex];
+  auto& cmdbuf     = swapbuffer.commandBuffer;
+
+  AcquireNextImage();
+
+  cmdbuf.Reset();
+  cmdbuf.Begin(true);
+
+  // change layouts if necessary
+  auto     barriers     = stack.Alloc< vk::ImageMemoryBarrier >(2);
+  uint32_t barrierIndex = 0;
+  // change depth/stencil attachment layout
+  if(mDepthStencilMode != DepthStencil::NONE && mDepthStencilLayoutChangeNeeded)
+  {
+    RecordDepthStencilBarrier(barriers[barrierIndex++]);
+    mDepthStencilLayoutChangeNeeded = false;
+  }
+
+  // change color attachment layout
+  if(swapbuffer.layout != vk::ImageLayout::eColorAttachmentOptimal)
+  {
+    RecordColorBarrier(barriers[barrierIndex++], swapbuffer);
+  }
+
+  // record pipeline barrier command
+  cmdbuf->pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe,
+                          vk::PipelineStageFlagBits::eTopOfPipe, vk::DependencyFlags(), 0, nullptr,
+                          0, nullptr, static_cast< uint32_t >(barrierIndex), &barriers[0]);
+
+  BeginRenderPass(cmdbuf);
+
+  stack.Rollback(frame);
+}
+
+void SwapchainImpl::AcquireNextImage()
+{
+  auto  device     = mDevice.GetVkDevice();
+  auto  semaphore  = mAcquireSemaphore[mCurrentBufferIndex];
+  auto& swapbuffer = mBuffers[mAcquiredBufferIndex];
+
+  // acquire new image
+  VkTestCall(device.acquireNextImageKHR(mVkSwapchain, 1000000u, semaphore, nullptr, &mAcquiredBufferIndex));
+
+  // check fence of selected buffer
+  if(swapbuffer.submitted)
+  {
+    // fixme: ugly busy wait which in most of cases should not happen
+
+    while(device.waitForFences(1, &swapbuffer.fence, false, 1000000) != vk::Result::eSuccess)
+    {
+    }
+  }
+  VkAssertCall(device.resetFences(1, &swapbuffer.fence));
+}
+
+void SwapchainImpl::RecordDepthStencilBarrier(vk::ImageMemoryBarrier& barrier)
+{
+  barrier.setImage(*mVkDepthStencilImage)
+      .setSubresourceRange(vk::ImageSubresourceRange()
+                               .setLayerCount(1)
+                               .setBaseArrayLayer(0)
+                               .setBaseMipLevel(0)
+                               .setLevelCount(1)
+                               .setLayerCount(1)
+                               .setAspectMask(vk::ImageAspectFlagBits::eDepth))
+      .setSrcAccessMask(vk::AccessFlagBits())
+      .setDstAccessMask(vk::AccessFlagBits::eDepthStencilAttachmentWrite)
+      .setOldLayout(vk::ImageLayout::eUndefined)
+      .setNewLayout(vk::ImageLayout::eDepthStencilAttachmentOptimal);
+}
+
+void SwapchainImpl::RecordColorBarrier(vk::ImageMemoryBarrier& barrier, SwapchainFramebuffer& swapbuffer)
+{
+  vk::AccessFlags srcAccess{};
+  if(swapbuffer.layout != vk::ImageLayout::eUndefined)
+  {
+    srcAccess = (vk::AccessFlagBits::eMemoryRead);
+  }
+
+  barrier.setImage(swapbuffer.image)
+      .setSubresourceRange(vk::ImageSubresourceRange()
+                               .setLayerCount(1)
+                               .setBaseArrayLayer(0)
+                               .setBaseMipLevel(0)
+                               .setLevelCount(1)
+                               .setLayerCount(1)
+                               .setAspectMask(vk::ImageAspectFlagBits::eColor))
+      .setSrcAccessMask(srcAccess)
+      .setDstAccessMask(vk::AccessFlagBits::eColorAttachmentWrite)
+      .setOldLayout(swapbuffer.layout)
+      .setNewLayout(vk::ImageLayout::eColorAttachmentOptimal);
+
+  swapbuffer.layout = vk::ImageLayout::eColorAttachmentOptimal;
+}
+
+void SwapchainImpl::BeginRenderPass(CommandBuffer& cmdbuf)
+{
+  auto& stack = mDevice.GetStack(0);
+  auto  frame = stack.Mark();
+
+  auto& swapbuffer = mBuffers[mAcquiredBufferIndex];
+  auto& area       = stack.AllocNewRef< vk::Rect2D >();
+  area.setOffset({0, 0}).setExtent({mSurface.GetWidth(), mSurface.GetHeight()});
+
+  // THIS CODE IS VERY TEMPORARY!!!
+  static float red = 0.0f;
+  red += 0.01f;
+  if(red > 1.0f)
+  {
+    red -= 1.0f;
+  }
+
+  // clear values
+  auto clearValues = stack.Alloc< vk::ClearValue >(2);
+
+  // clear color
+  clearValues[0] = vk::ClearValue().color.setFloat32({red, 0.0f, 0.0f, 1.0f});
+
+  // clear depth/stencil
+  clearValues[1] = vk::ClearValue().depthStencil.setDepth(1.0f).setStencil(0);
+
+  // begin main render pass
+  auto& rpInfo = stack.AllocNewRef< vk::RenderPassBeginInfo >();
+  rpInfo.setRenderPass(mRenderPass)
+      .setRenderArea(area)
+      .setPClearValues(clearValues)
+      .setClearValueCount(mDepthStencilMode != DepthStencil::NONE ? 2 : 1)
+      .setFramebuffer(swapbuffer.framebuffer);
+
+  // begin render pass
+  cmdbuf->beginRenderPass(&rpInfo, vk::SubpassContents::eInline);
+
+  stack.Rollback(frame);
+}
+
+void SwapchainImpl::Present()
+{
+  Present(mDevice.GetCommandQueue(0, QueueType::PRESENT));
+}
+
+void SwapchainImpl::Present(const CommandQueue& queue)
+{
+  auto& swapbuffer = mBuffers[mAcquiredBufferIndex];
+  auto& cmdbuf     = swapbuffer.commandBuffer;
+
+  cmdbuf->endRenderPass();
+  cmdbuf.End();
+
+  vk::PipelineStageFlags waitFlags = vk::PipelineStageFlagBits::eColorAttachmentOutput;
+
+  // submit command buffer
+  queue.Submit(&cmdbuf, 1, &mAcquireSemaphore[mCurrentBufferIndex], 1, // wait for acquire sem
+               &mPresentSemaphore[mCurrentBufferIndex], 1,             // signal present sem
+               &waitFlags, swapbuffer.fence);
+
+  // present
+  vk::PresentInfoKHR presentInfo;
+  presentInfo.setPImageIndices(&mAcquiredBufferIndex)
+      .setPResults(nullptr)
+      .setPSwapchains(&mVkSwapchain)
+      .setSwapchainCount(1)
+      .setWaitSemaphoreCount(1)
+      .setPWaitSemaphores(&mPresentSemaphore[mCurrentBufferIndex]);
+
+  VkAssertCall(queue.GetVkQueue().presentKHR(&presentInfo));
+
+  // set swap buffer image layout manually ( will be changed with end of the render pass automatically )
+  swapbuffer.layout    = vk::ImageLayout::ePresentSrcKHR;
+  swapbuffer.submitted = true;
+
+  // increase "logical" buffer
+  mCurrentBufferIndex = (mCurrentBufferIndex + 1) % (mMaxBufferCount + 1);
+}
+
+namespace
+{
+SwapchainImpl* GetImpl(const Swapchain* handle)
+{
+  return static_cast< SwapchainImpl* >(handle->GetObject());
+}
+}
+
+Swapchain Swapchain::New(const LogicalDevice& context, const Vulkan::Surface& surface,
+                         uint32_t bufferCount, DepthStencil depthStencil)
+{
+  return Swapchain(new SwapchainImpl(context, surface, bufferCount, depthStencil));
+}
+
+const CommandBuffer& Swapchain::GetCommandBuffer(uint32_t index) const
+{
+  return GetImpl(this)->GetCommandBuffer(index);
+}
+
+const CommandBuffer& Swapchain::GetCurrentCommandBuffer() const
+{
+  return GetImpl(this)->GetCurrentCommandBuffer();
+}
+
+const vk::Image& Swapchain::GetCurrentImage() const
+{
+  return GetImpl(this)->GetCurrentImage();
+}
+
+} // Vulkan
+} // Graphics
+} // Dali
diff --git a/dali/graphics/vulkan/swapchain.h b/dali/graphics/vulkan/swapchain.h
new file mode 100644 (file)
index 0000000..38faee7
--- /dev/null
@@ -0,0 +1,65 @@
+#ifndef DALI_CORE_GRAPHICS_VULKAN_SWAPCHAIN_H
+#define DALI_CORE_GRAPHICS_VULKAN_SWAPCHAIN_H
+
+/*
+ * Copyright (c) 2017 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/graphics/graphics-swapchain.h>
+#include <dali/graphics/vulkan/common.h>
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace Vulkan
+{
+
+class Surface;
+class LogicalDevice;
+class CommandBuffer;
+
+/**
+ * In computer graphics swap chain represents a series of images which are sort of
+ * virtual framebuffers.
+ * Swapchain class manages mentioned images ( swaps them when needed for example on vsync )
+ * and delivers an image to the graphics API as a render target bound to
+ * the surface ( simplifying, delivers main framebuffer to render to ).
+ */
+class Swapchain : public GraphicsSwapchain
+{
+public:
+  Swapchain(Integration::GraphicsSwapchainBase* impl = nullptr) : GraphicsSwapchain{impl}
+  {
+  }
+
+  using GraphicsSwapchain::operator=;
+
+  static Swapchain New(const LogicalDevice& device, const Surface& surface, uint32_t bufferCount,
+                       DepthStencil depthStencil);
+
+  const CommandBuffer& GetCommandBuffer(uint32_t index) const;
+
+  const CommandBuffer& GetCurrentCommandBuffer() const;
+
+  const vk::Image& GetCurrentImage() const;
+};
+
+} // Vulkan
+} // Graphics
+} // Dali
+
+#endif //DALI_CORE_GRAPHICS_VULKAN_SWAPCHAIN_H