Vulkan SDK for Android 1.1.1 Mali Developer Center
linux.cpp
1 /* Copyright (c) 2016-2017, ARM Limited and Contributors
2  *
3  * SPDX-License-Identifier: MIT
4  *
5  * Permission is hereby granted, free of charge,
6  * to any person obtaining a copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation the rights to
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
14  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
16  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
17  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19  */
20 
21 #include "framework/application.hpp"
22 
23 #include "framework/common.hpp"
24 #include "platform/os.hpp"
25 #include "platform/platform.hpp"
26 
27 #include "linux.hpp"
28 #include <limits.h>
29 #include <stdio.h>
30 #include <unistd.h>
31 
32 using namespace std;
33 
34 namespace MaliSDK
35 {
36 LinuxAssetManager::LinuxAssetManager()
37 {
38  pid_t pid = getpid();
39  char buf[PATH_MAX];
40 
41  static const char *exts[] = { "exe", "file", "path/a.out" };
42  for (auto ext : exts)
43  {
44  string linkPath = "/proc/";
45  linkPath += to_string(pid);
46  linkPath += '/';
47  linkPath += ext;
48 
49  ssize_t ret = readlink(linkPath.c_str(), buf, sizeof(buf) - 1);
50  if (ret >= 0)
51  {
52  buf[ret] = '\0';
53  basePath = buf;
54 
55  auto pos = basePath.find_last_of('/');
56  if (pos == string::npos)
57  basePath = ".";
58  else
59  basePath = basePath.substr(0, pos);
60 
61  LOGI("Found application base directory: \"%s\".\n", basePath.c_str());
62  return;
63  }
64  }
65 
66  LOGE("Could not find application path based on /proc/$pid interface. Will "
67  "use working directory instead.\n");
68  basePath = ".";
69 }
70 
71 Result LinuxAssetManager::readBinaryFile(const char *pPath, void **ppData, size_t *pSize)
72 {
73  auto fullpath = basePath + "/assets/" + pPath;
74  return AssetManager::readBinaryFile(fullpath.c_str(), ppData, pSize);
75 }
76 
77 AssetManager &OS::getAssetManager()
78 {
79  static LinuxAssetManager manager;
80  return manager;
81 }
82 
83 double OS::getCurrentTime()
84 {
85  timespec ts;
86  if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0)
87  {
88  LOGE("clock_gettime() failed.\n");
89  return 0.0;
90  }
91 
92  return ts.tv_sec + ts.tv_nsec * 1e-9;
93 }
94 
95 unsigned OS::getNumberOfCpuThreads()
96 {
97  long cpus = sysconf(_SC_NPROCESSORS_ONLN);
98  if (cpus > 0)
99  {
100  LOGI("Detected %ld CPUs.\n", cpus);
101  return unsigned(cpus);
102  }
103  else
104  {
105  LOGE("Failed to detect number of CPUs, assuming 1.\n");
106  return 1;
107  }
108 }
109 }
110 
111 using namespace MaliSDK;
112 
113 int main(int argc, char **argv)
114 {
115  Platform &platform = Platform::get();
116  if (FAILED(platform.initialize()))
117  {
118  LOGE("Failed to initialize platform.\n");
119  return 1;
120  }
121 
123  if (FAILED(platform.createWindow(dim)))
124  {
125  LOGE("Failed to create platform window.\n");
126  return 1;
127  }
128 
129  VulkanApplication *app = createApplication();
130  if (!app)
131  {
132  LOGE("Failed to create application.\n");
133  return 1;
134  }
135 
136  if (!app->initialize(&platform.getContext()))
137  {
138  LOGE("Failed to initialize application.\n");
139  return 1;
140  }
141 
142  vector<VkImage> images;
143  platform.getCurrentSwapchain(&images, &dim);
144  app->updateSwapchain(images, dim);
145 
146  unsigned frameCount = 0;
147  double startTime = OS::getCurrentTime();
148 
149  unsigned maxFrameCount = 0;
150  bool useMaxFrameCount = false;
151  if (argc == 2)
152  {
153  maxFrameCount = strtoul(argv[1], nullptr, 0);
154  useMaxFrameCount = true;
155  }
156 
157  while (platform.getWindowStatus() == Platform::STATUS_RUNNING)
158  {
159  unsigned index;
160  Result res = platform.acquireNextImage(&index);
161  while (res == RESULT_ERROR_OUTDATED_SWAPCHAIN)
162  {
163  res = platform.acquireNextImage(&index);
164  platform.getCurrentSwapchain(&images, &dim);
165  app->updateSwapchain(images, dim);
166  }
167 
168  if (FAILED(res))
169  {
170  LOGE("Unrecoverable swapchain error.\n");
171  break;
172  }
173 
174  app->render(index, 0.0166f);
175  res = platform.presentImage(index);
176 
177  // Handle Outdated error in acquire.
178  if (FAILED(res) && res != RESULT_ERROR_OUTDATED_SWAPCHAIN)
179  break;
180 
181  frameCount++;
182  if (frameCount == 100)
183  {
184  double endTime = OS::getCurrentTime();
185  LOGI("FPS: %.3f\n", frameCount / (endTime - startTime));
186  frameCount = 0;
187  startTime = endTime;
188  }
189 
190  if (useMaxFrameCount && (--maxFrameCount == 0))
191  break;
192  }
193 
194  app->terminate();
195  delete app;
196  platform.terminate();
197 }
The Linux asset manager. It is based on regular fopen(), with the exception that all paths passed to ...
Definition: linux.hpp:35
The asset manager reads data from a platform specific location. This class is used internally to load...
virtual void terminate()=0
Destructor for the class.
virtual Result initialize()=0
Initializes the platform.
virtual void getCurrentSwapchain(std::vector< VkImage > *images, SwapchainDimensions *swapchain)=0
Gets the current swapchain.
virtual void render(unsigned swapchainIndex, float deltaTime)=0
Render a frame.
virtual void updateSwapchain(const std::vector< VkImage > &backbuffers, const Platform::SwapchainDimensions &dimensions)=0
Called when the swapchain has been initialized.
Describes the size and format of the swapchain.
Definition: platform.hpp:54
virtual Result createWindow(const SwapchainDimensions &swapchain)=0
Creates a window with desired swapchain dimensions.
Context & getContext()
Gets the context owned by the platform.
Definition: platform.hpp:76
The platform class is to abstract the Vulkan implementation of a particular platform. It is not used directly by applications, but by the mainloop implementation which is OS specific.
Definition: platform.hpp:38
virtual Status getWindowStatus()=0
Gets current window status.
VulkanApplication is inherited by all samples. The common platform code will run the main loop and ta...
Definition: application.hpp:33
virtual Result presentImage(unsigned index)=0
Presents an image to the swapchain.
virtual bool initialize(Context *pContext)=0
This function is called when the context is brought up and is the constructor of this class...
virtual Result acquireNextImage(unsigned *index)=0
At start of a frame, acquire the next swapchain image to render into.
virtual void terminate()=0
Terminates the platform.
virtual SwapchainDimensions getPreferredSwapchain()=0
Gets the preferred swapchain size. Not relevant for all platforms.