aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTony Barbour <tony@LunarG.com>2016-02-25 15:44:10 -0700
committerTony Barbour <tony@LunarG.com>2016-02-26 13:53:07 -0700
commit6d366c23f50752c8bc39673416040d89a94a586f (patch)
tree7a9493a747ffad8b708fd373ffbee359459ddd66
parent2e4f6dfe4624d966fb4db3c477586bd6b1c2b8e1 (diff)
downloadusermoji-6d366c23f50752c8bc39673416040d89a94a586f.tar.xz
demos: Add Hologram snapshot as Smoke test/demo
-rwxr-xr-xCMakeLists.txt1
-rw-r--r--demos/CMakeLists.txt3
-rw-r--r--demos/smoke/CMakeLists.txt79
-rw-r--r--demos/smoke/Game.h133
-rw-r--r--demos/smoke/Helpers.h131
-rw-r--r--demos/smoke/HelpersDispatchTable.cpp527
-rw-r--r--demos/smoke/HelpersDispatchTable.h220
-rw-r--r--demos/smoke/Main.cpp90
-rw-r--r--demos/smoke/Meshes.cpp537
-rw-r--r--demos/smoke/Meshes.h67
-rw-r--r--demos/smoke/Meshes.teapot.h2666
-rw-r--r--demos/smoke/README.md1
-rw-r--r--demos/smoke/Shell.cpp591
-rw-r--r--demos/smoke/Shell.h162
-rw-r--r--demos/smoke/ShellAndroid.cpp227
-rw-r--r--demos/smoke/ShellAndroid.h68
-rw-r--r--demos/smoke/ShellWin32.cpp256
-rw-r--r--demos/smoke/ShellWin32.h63
-rw-r--r--demos/smoke/ShellXcb.cpp344
-rw-r--r--demos/smoke/ShellXcb.h62
-rw-r--r--demos/smoke/Simulation.cpp327
-rw-r--r--demos/smoke/Simulation.h112
-rw-r--r--demos/smoke/Smoke.cpp915
-rw-r--r--demos/smoke/Smoke.frag12
-rw-r--r--demos/smoke/Smoke.h195
-rw-r--r--demos/smoke/Smoke.push_constant.vert27
-rw-r--r--demos/smoke/Smoke.vert27
-rwxr-xr-xdemos/smoke/android/build-and-install30
-rw-r--r--demos/smoke/android/build.gradle87
-rw-r--r--demos/smoke/android/gradle/wrapper/gradle-wrapper.jarbin0 -> 53636 bytes
-rw-r--r--demos/smoke/android/gradle/wrapper/gradle-wrapper.properties6
-rwxr-xr-xdemos/smoke/android/gradlew160
-rw-r--r--demos/smoke/android/gradlew.bat90
-rw-r--r--demos/smoke/android/src/main/AndroidManifest.xml20
-rw-r--r--demos/smoke/android/src/main/jni/Smoke.frag.h78
-rw-r--r--demos/smoke/android/src/main/jni/Smoke.push_constant.vert.h352
-rw-r--r--demos/smoke/android/src/main/jni/Smoke.vert.h354
-rw-r--r--demos/smoke/android/src/main/res/values/strings.xml4
-rwxr-xr-xdemos/smoke/generate-dispatch-table498
-rwxr-xr-xdemos/smoke/glsl-to-spirv100
40 files changed, 9622 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 14340336..5be176be 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -11,6 +11,7 @@ project (VULKAN)
# vulkan-<major>.dll (and other files).
set(MAJOR "1")
+find_package(PythonInterp 3 REQUIRED)
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
add_definitions(-DVK_USE_PLATFORM_WIN32_KHR -DWIN32_LEAN_AND_MEAN)
diff --git a/demos/CMakeLists.txt b/demos/CMakeLists.txt
index e8424d65..580692c7 100644
--- a/demos/CMakeLists.txt
+++ b/demos/CMakeLists.txt
@@ -110,3 +110,6 @@ else()
add_executable(cube WIN32 cube.c ${CMAKE_BINARY_DIR}/demos/cube-vert.spv ${CMAKE_BINARY_DIR}/demos/cube-frag.spv)
target_link_libraries(cube ${LIBRARIES} )
endif()
+
+add_subdirectory(smoke)
+
diff --git a/demos/smoke/CMakeLists.txt b/demos/smoke/CMakeLists.txt
new file mode 100644
index 00000000..0c3dd1cd
--- /dev/null
+++ b/demos/smoke/CMakeLists.txt
@@ -0,0 +1,79 @@
+set(GLSLANG_VALIDATOR ${GLSLANG_PREFIX}/build/install/bin/glslangValidator)
+set (GLMINC_PREFIX ${PROJECT_SOURCE_DIR}/libs)
+
+macro(generate_dispatch_table out)
+ add_custom_command(OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/${out}
+ COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/generate-dispatch-table ${CMAKE_CURRENT_SOURCE_DIR}/${out}
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/generate-dispatch-table
+ )
+endmacro()
+
+macro(glsl_to_spirv src)
+ add_custom_command(OUTPUT ${src}.h
+ COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/glsl-to-spirv ${CMAKE_CURRENT_SOURCE_DIR}/${src} ${src}.h ${GLSLANG_VALIDATOR}
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/glsl-to-spirv ${CMAKE_CURRENT_SOURCE_DIR}/${src} ${GLSLANG_VALIDATOR}
+ )
+endmacro()
+
+generate_dispatch_table(HelpersDispatchTable.h)
+generate_dispatch_table(HelpersDispatchTable.cpp)
+glsl_to_spirv(Smoke.frag)
+glsl_to_spirv(Smoke.vert)
+glsl_to_spirv(Smoke.push_constant.vert)
+
+set(sources
+ Game.h
+ Helpers.h
+ HelpersDispatchTable.cpp
+ HelpersDispatchTable.h
+ Smoke.cpp
+ Smoke.h
+ Smoke.frag.h
+ Smoke.vert.h
+ Smoke.push_constant.vert.h
+ Main.cpp
+ Meshes.cpp
+ Meshes.h
+ Meshes.teapot.h
+ Simulation.cpp
+ Simulation.h
+ Shell.cpp
+ Shell.h
+ )
+
+set(definitions
+ PRIVATE -DVK_NO_PROTOTYPES
+ PRIVATE -DGLM_FORCE_RADIANS)
+
+set(includes
+ PRIVATE ${GLMINC_PREFIX}
+ PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
+
+set(libraries PRIVATE ${CMAKE_THREAD_LIBS_INIT})
+
+if(TARGET vulkan)
+ get_property(vulkan_location TARGET vulkan PROPERTY LOCATION)
+ list(APPEND definitions PRIVATE -DUNINSTALLED_LOADER="${vulkan_location}")
+endif()
+
+if(WIN32)
+ list(APPEND definitions PRIVATE -DVK_USE_PLATFORM_WIN32_KHR)
+ list(APPEND definitions PRIVATE -DWIN32_LEAN_AND_MEAN)
+
+ list(APPEND sources ShellWin32.cpp ShellWin32.h)
+else()
+ list(APPEND libraries PRIVATE -ldl)
+
+ find_package(XCB REQUIRED)
+
+ list(APPEND sources ShellXcb.cpp ShellXcb.h)
+ list(APPEND definitions PRIVATE -DVK_USE_PLATFORM_XCB_KHR)
+ list(APPEND includes PRIVATE ${XCB_INCLUDES})
+ list(APPEND libraries PRIVATE ${XCB_LIBRARIES})
+endif()
+
+
+add_executable(smoke ${sources})
+target_compile_definitions(smoke ${definitions})
+target_include_directories(smoke ${includes})
+target_link_libraries(smoke ${libraries})
diff --git a/demos/smoke/Game.h b/demos/smoke/Game.h
new file mode 100644
index 00000000..00bbf378
--- /dev/null
+++ b/demos/smoke/Game.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2016 Google, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef GAME_H
+#define GAME_H
+
+#include <string>
+#include <vector>
+
+class Shell;
+
+class Game {
+public:
+ Game(const Game &game) = delete;
+ Game &operator=(const Game &game) = delete;
+ virtual ~Game() {}
+
+ struct Settings {
+ std::string name;
+ int initial_width;
+ int initial_height;
+ int queue_count;
+ int back_buffer_count;
+ int ticks_per_second;
+ bool vsync;
+ bool animate;
+
+ bool validate;
+ bool validate_verbose;
+
+ bool no_tick;
+ bool no_render;
+ bool no_present;
+ };
+ const Settings &settings() const { return settings_; }
+
+ virtual void attach_shell(Shell &shell) { shell_ = &shell; }
+ virtual void detach_shell() { shell_ = nullptr; }
+
+ virtual void attach_swapchain() {}
+ virtual void detach_swapchain() {}
+
+ enum Key {
+ // virtual keys
+ KEY_SHUTDOWN,
+ // physical keys
+ KEY_UNKNOWN,
+ KEY_ESC,
+ KEY_UP,
+ KEY_DOWN,
+ KEY_SPACE,
+ };
+ virtual void on_key(Key key) {}
+ virtual void on_tick() {}
+
+ virtual void on_frame(float frame_pred) {}
+
+protected:
+ Game(const std::string &name, const std::vector<std::string> &args)
+ : settings_(), shell_(nullptr)
+ {
+ settings_.name = name;
+ settings_.initial_width = 1280;
+ settings_.initial_height = 1024;
+ settings_.queue_count = 1;
+ settings_.back_buffer_count = 1;
+ settings_.ticks_per_second = 30;
+ settings_.vsync = true;
+ settings_.animate = true;
+
+ settings_.validate = false;
+ settings_.validate_verbose = false;
+
+ settings_.no_tick = false;
+ settings_.no_render = false;
+ settings_.no_present = false;
+
+ parse_args(args);
+ }
+
+ Settings settings_;
+ Shell *shell_;
+
+private:
+ void parse_args(const std::vector<std::string> &args)
+ {
+ for (auto it = args.begin(); it != args.end(); ++it) {
+ if (*it == "-b") {
+ settings_.vsync = false;
+ } else if (*it == "-w") {
+ ++it;
+ settings_.initial_width = std::stoi(*it);
+ } else if (*it == "-h") {
+ ++it;
+ settings_.initial_height = std::stoi(*it);
+ } else if (*it == "-v") {
+ settings_.validate = true;
+ } else if (*it == "--validate") {
+ settings_.validate = true;
+ } else if (*it == "-vv") {
+ settings_.validate = true;
+ settings_.validate_verbose = true;
+ } else if (*it == "-nt") {
+ settings_.no_tick = true;
+ } else if (*it == "-nr") {
+ settings_.no_render = true;
+ } else if (*it == "-np") {
+ settings_.no_present = true;
+ }
+ }
+ }
+};
+
+#endif // GAME_H
diff --git a/demos/smoke/Helpers.h b/demos/smoke/Helpers.h
new file mode 100644
index 00000000..6b889abc
--- /dev/null
+++ b/demos/smoke/Helpers.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2016 Google, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef HELPERS_H
+#define HELPERS_H
+
+#include <vector>
+#include <sstream>
+#include <stdexcept>
+#include <vulkan/vulkan.h>
+
+#include "HelpersDispatchTable.h"
+
+namespace vk {
+
+inline VkResult assert_success(VkResult res)
+{
+ if (res != VK_SUCCESS) {
+ std::stringstream ss;
+ ss << "VkResult " << res << " returned";
+ throw std::runtime_error(ss.str());
+ }
+
+ return res;
+}
+
+inline VkResult enumerate(const char *layer, std::vector<VkExtensionProperties> &exts)
+{
+ uint32_t count = 0;
+ vk::EnumerateInstanceExtensionProperties(layer, &count, nullptr);
+
+ exts.resize(count);
+ return vk::EnumerateInstanceExtensionProperties(layer, &count, exts.data());
+}
+
+inline VkResult enumerate(VkPhysicalDevice phy, const char *layer, std::vector<VkExtensionProperties> &exts)
+{
+ uint32_t count = 0;
+ vk::EnumerateDeviceExtensionProperties(phy, layer, &count, nullptr);
+
+ exts.resize(count);
+ return vk::EnumerateDeviceExtensionProperties(phy, layer, &count, exts.data());
+}
+
+inline VkResult enumerate(VkInstance instance, std::vector<VkPhysicalDevice> &phys)
+{
+ uint32_t count = 0;
+ vk::EnumeratePhysicalDevices(instance, &count, nullptr);
+
+ phys.resize(count);
+ return vk::EnumeratePhysicalDevices(instance, &count, phys.data());
+}
+
+inline VkResult enumerate(std::vector<VkLayerProperties> &layer_props)
+{
+ uint32_t count = 0;
+ vk::EnumerateInstanceLayerProperties(&count, nullptr);
+
+ layer_props.resize(count);
+ return vk::EnumerateInstanceLayerProperties(&count, layer_props.data());
+}
+
+inline VkResult enumerate(VkPhysicalDevice phy, std::vector<VkLayerProperties> &layer_props)
+{
+ uint32_t count = 0;
+ vk::EnumerateDeviceLayerProperties(phy, &count, nullptr);
+
+ layer_props.resize(count);
+ return vk::EnumerateDeviceLayerProperties(phy, &count, layer_props.data());
+}
+
+inline VkResult get(VkPhysicalDevice phy, std::vector<VkQueueFamilyProperties> &queues)
+{
+ uint32_t count = 0;
+ vk::GetPhysicalDeviceQueueFamilyProperties(phy, &count, nullptr);
+
+ queues.resize(count);
+ vk::GetPhysicalDeviceQueueFamilyProperties(phy, &count, queues.data());
+
+ return VK_SUCCESS;
+}
+
+inline VkResult get(VkPhysicalDevice phy, VkSurfaceKHR surface, std::vector<VkSurfaceFormatKHR> &formats)
+{
+ uint32_t count = 0;
+ vk::GetPhysicalDeviceSurfaceFormatsKHR(phy, surface, &count, nullptr);
+
+ formats.resize(count);
+ return vk::GetPhysicalDeviceSurfaceFormatsKHR(phy, surface, &count, formats.data());
+}
+
+inline VkResult get(VkPhysicalDevice phy, VkSurfaceKHR surface, std::vector<VkPresentModeKHR> &modes)
+{
+ uint32_t count = 0;
+ vk::GetPhysicalDeviceSurfacePresentModesKHR(phy, surface, &count, nullptr);
+
+ modes.resize(count);
+ return vk::GetPhysicalDeviceSurfacePresentModesKHR(phy, surface, &count, modes.data());
+}
+
+inline VkResult get(VkDevice dev, VkSwapchainKHR swapchain, std::vector<VkImage> &images)
+{
+ uint32_t count = 0;
+ vk::GetSwapchainImagesKHR(dev, swapchain, &count, nullptr);
+
+ images.resize(count);
+ return vk::GetSwapchainImagesKHR(dev, swapchain, &count, images.data());
+}
+
+} // namespace vk
+
+#endif // HELPERS_H
diff --git a/demos/smoke/HelpersDispatchTable.cpp b/demos/smoke/HelpersDispatchTable.cpp
new file mode 100644
index 00000000..e9b34361
--- /dev/null
+++ b/demos/smoke/HelpersDispatchTable.cpp
@@ -0,0 +1,527 @@
+// This file is generated.
+#include "HelpersDispatchTable.h"
+
+namespace vk {
+
+PFN_vkCreateInstance CreateInstance;
+PFN_vkDestroyInstance DestroyInstance;
+PFN_vkEnumeratePhysicalDevices EnumeratePhysicalDevices;
+PFN_vkGetPhysicalDeviceFeatures GetPhysicalDeviceFeatures;
+PFN_vkGetPhysicalDeviceFormatProperties GetPhysicalDeviceFormatProperties;
+PFN_vkGetPhysicalDeviceImageFormatProperties GetPhysicalDeviceImageFormatProperties;
+PFN_vkGetPhysicalDeviceProperties GetPhysicalDeviceProperties;
+PFN_vkGetPhysicalDeviceQueueFamilyProperties GetPhysicalDeviceQueueFamilyProperties;
+PFN_vkGetPhysicalDeviceMemoryProperties GetPhysicalDeviceMemoryProperties;
+PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
+PFN_vkGetDeviceProcAddr GetDeviceProcAddr;
+PFN_vkCreateDevice CreateDevice;
+PFN_vkDestroyDevice DestroyDevice;
+PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties;
+PFN_vkEnumerateDeviceExtensionProperties EnumerateDeviceExtensionProperties;
+PFN_vkEnumerateInstanceLayerProperties EnumerateInstanceLayerProperties;
+PFN_vkEnumerateDeviceLayerProperties EnumerateDeviceLayerProperties;
+PFN_vkGetDeviceQueue GetDeviceQueue;
+PFN_vkQueueSubmit QueueSubmit;
+PFN_vkQueueWaitIdle QueueWaitIdle;
+PFN_vkDeviceWaitIdle DeviceWaitIdle;
+PFN_vkAllocateMemory AllocateMemory;
+PFN_vkFreeMemory FreeMemory;
+PFN_vkMapMemory MapMemory;
+PFN_vkUnmapMemory UnmapMemory;
+PFN_vkFlushMappedMemoryRanges FlushMappedMemoryRanges;
+PFN_vkInvalidateMappedMemoryRanges InvalidateMappedMemoryRanges;
+PFN_vkGetDeviceMemoryCommitment GetDeviceMemoryCommitment;
+PFN_vkBindBufferMemory BindBufferMemory;
+PFN_vkBindImageMemory BindImageMemory;
+PFN_vkGetBufferMemoryRequirements GetBufferMemoryRequirements;
+PFN_vkGetImageMemoryRequirements GetImageMemoryRequirements;
+PFN_vkGetImageSparseMemoryRequirements GetImageSparseMemoryRequirements;
+PFN_vkGetPhysicalDeviceSparseImageFormatProperties GetPhysicalDeviceSparseImageFormatProperties;
+PFN_vkQueueBindSparse QueueBindSparse;
+PFN_vkCreateFence CreateFence;
+PFN_vkDestroyFence DestroyFence;
+PFN_vkResetFences ResetFences;
+PFN_vkGetFenceStatus GetFenceStatus;
+PFN_vkWaitForFences WaitForFences;
+PFN_vkCreateSemaphore CreateSemaphore;
+PFN_vkDestroySemaphore DestroySemaphore;
+PFN_vkCreateEvent CreateEvent;
+PFN_vkDestroyEvent DestroyEvent;
+PFN_vkGetEventStatus GetEventStatus;
+PFN_vkSetEvent SetEvent;
+PFN_vkResetEvent ResetEvent;
+PFN_vkCreateQueryPool CreateQueryPool;
+PFN_vkDestroyQueryPool DestroyQueryPool;
+PFN_vkGetQueryPoolResults GetQueryPoolResults;
+PFN_vkCreateBuffer CreateBuffer;
+PFN_vkDestroyBuffer DestroyBuffer;
+PFN_vkCreateBufferView CreateBufferView;
+PFN_vkDestroyBufferView DestroyBufferView;
+PFN_vkCreateImage CreateImage;
+PFN_vkDestroyImage DestroyImage;
+PFN_vkGetImageSubresourceLayout GetImageSubresourceLayout;
+PFN_vkCreateImageView CreateImageView;
+PFN_vkDestroyImageView DestroyImageView;
+PFN_vkCreateShaderModule CreateShaderModule;
+PFN_vkDestroyShaderModule DestroyShaderModule;
+PFN_vkCreatePipelineCache CreatePipelineCache;
+PFN_vkDestroyPipelineCache DestroyPipelineCache;
+PFN_vkGetPipelineCacheData GetPipelineCacheData;
+PFN_vkMergePipelineCaches MergePipelineCaches;
+PFN_vkCreateGraphicsPipelines CreateGraphicsPipelines;
+PFN_vkCreateComputePipelines CreateComputePipelines;
+PFN_vkDestroyPipeline DestroyPipeline;
+PFN_vkCreatePipelineLayout CreatePipelineLayout;
+PFN_vkDestroyPipelineLayout DestroyPipelineLayout;
+PFN_vkCreateSampler CreateSampler;
+PFN_vkDestroySampler DestroySampler;
+PFN_vkCreateDescriptorSetLayout CreateDescriptorSetLayout;
+PFN_vkDestroyDescriptorSetLayout DestroyDescriptorSetLayout;
+PFN_vkCreateDescriptorPool CreateDescriptorPool;
+PFN_vkDestroyDescriptorPool DestroyDescriptorPool;
+PFN_vkResetDescriptorPool ResetDescriptorPool;
+PFN_vkAllocateDescriptorSets AllocateDescriptorSets;
+PFN_vkFreeDescriptorSets FreeDescriptorSets;
+PFN_vkUpdateDescriptorSets UpdateDescriptorSets;
+PFN_vkCreateFramebuffer CreateFramebuffer;
+PFN_vkDestroyFramebuffer DestroyFramebuffer;
+PFN_vkCreateRenderPass CreateRenderPass;
+PFN_vkDestroyRenderPass DestroyRenderPass;
+PFN_vkGetRenderAreaGranularity GetRenderAreaGranularity;
+PFN_vkCreateCommandPool CreateCommandPool;
+PFN_vkDestroyCommandPool DestroyCommandPool;
+PFN_vkResetCommandPool ResetCommandPool;
+PFN_vkAllocateCommandBuffers AllocateCommandBuffers;
+PFN_vkFreeCommandBuffers FreeCommandBuffers;
+PFN_vkBeginCommandBuffer BeginCommandBuffer;
+PFN_vkEndCommandBuffer EndCommandBuffer;
+PFN_vkResetCommandBuffer ResetCommandBuffer;
+PFN_vkCmdBindPipeline CmdBindPipeline;
+PFN_vkCmdSetViewport CmdSetViewport;
+PFN_vkCmdSetScissor CmdSetScissor;
+PFN_vkCmdSetLineWidth CmdSetLineWidth;
+PFN_vkCmdSetDepthBias CmdSetDepthBias;
+PFN_vkCmdSetBlendConstants CmdSetBlendConstants;
+PFN_vkCmdSetDepthBounds CmdSetDepthBounds;
+PFN_vkCmdSetStencilCompareMask CmdSetStencilCompareMask;
+PFN_vkCmdSetStencilWriteMask CmdSetStencilWriteMask;
+PFN_vkCmdSetStencilReference CmdSetStencilReference;
+PFN_vkCmdBindDescriptorSets CmdBindDescriptorSets;
+PFN_vkCmdBindIndexBuffer CmdBindIndexBuffer;
+PFN_vkCmdBindVertexBuffers CmdBindVertexBuffers;
+PFN_vkCmdDraw CmdDraw;
+PFN_vkCmdDrawIndexed CmdDrawIndexed;
+PFN_vkCmdDrawIndirect CmdDrawIndirect;
+PFN_vkCmdDrawIndexedIndirect CmdDrawIndexedIndirect;
+PFN_vkCmdDispatch CmdDispatch;
+PFN_vkCmdDispatchIndirect CmdDispatchIndirect;
+PFN_vkCmdCopyBuffer CmdCopyBuffer;
+PFN_vkCmdCopyImage CmdCopyImage;
+PFN_vkCmdBlitImage CmdBlitImage;
+PFN_vkCmdCopyBufferToImage CmdCopyBufferToImage;
+PFN_vkCmdCopyImageToBuffer CmdCopyImageToBuffer;
+PFN_vkCmdUpdateBuffer CmdUpdateBuffer;
+PFN_vkCmdFillBuffer CmdFillBuffer;
+PFN_vkCmdClearColorImage CmdClearColorImage;
+PFN_vkCmdClearDepthStencilImage CmdClearDepthStencilImage;
+PFN_vkCmdClearAttachments CmdClearAttachments;
+PFN_vkCmdResolveImage CmdResolveImage;
+PFN_vkCmdSetEvent CmdSetEvent;
+PFN_vkCmdResetEvent CmdResetEvent;
+PFN_vkCmdWaitEvents CmdWaitEvents;
+PFN_vkCmdPipelineBarrier CmdPipelineBarrier;
+PFN_vkCmdBeginQuery CmdBeginQuery;
+PFN_vkCmdEndQuery CmdEndQuery;
+PFN_vkCmdResetQueryPool CmdResetQueryPool;
+PFN_vkCmdWriteTimestamp CmdWriteTimestamp;
+PFN_vkCmdCopyQueryPoolResults CmdCopyQueryPoolResults;
+PFN_vkCmdPushConstants CmdPushConstants;
+PFN_vkCmdBeginRenderPass CmdBeginRenderPass;
+PFN_vkCmdNextSubpass CmdNextSubpass;
+PFN_vkCmdEndRenderPass CmdEndRenderPass;
+PFN_vkCmdExecuteCommands CmdExecuteCommands;
+PFN_vkDestroySurfaceKHR DestroySurfaceKHR;
+PFN_vkGetPhysicalDeviceSurfaceSupportKHR GetPhysicalDeviceSurfaceSupportKHR;
+PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR GetPhysicalDeviceSurfaceCapabilitiesKHR;
+PFN_vkGetPhysicalDeviceSurfaceFormatsKHR GetPhysicalDeviceSurfaceFormatsKHR;
+PFN_vkGetPhysicalDeviceSurfacePresentModesKHR GetPhysicalDeviceSurfacePresentModesKHR;
+PFN_vkCreateSwapchainKHR CreateSwapchainKHR;
+PFN_vkDestroySwapchainKHR DestroySwapchainKHR;
+PFN_vkGetSwapchainImagesKHR GetSwapchainImagesKHR;
+PFN_vkAcquireNextImageKHR AcquireNextImageKHR;
+PFN_vkQueuePresentKHR QueuePresentKHR;
+PFN_vkGetPhysicalDeviceDisplayPropertiesKHR GetPhysicalDeviceDisplayPropertiesKHR;
+PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR GetPhysicalDeviceDisplayPlanePropertiesKHR;
+PFN_vkGetDisplayPlaneSupportedDisplaysKHR GetDisplayPlaneSupportedDisplaysKHR;
+PFN_vkGetDisplayModePropertiesKHR GetDisplayModePropertiesKHR;
+PFN_vkCreateDisplayModeKHR CreateDisplayModeKHR;
+PFN_vkGetDisplayPlaneCapabilitiesKHR GetDisplayPlaneCapabilitiesKHR;
+PFN_vkCreateDisplayPlaneSurfaceKHR CreateDisplayPlaneSurfaceKHR;
+PFN_vkCreateSharedSwapchainsKHR CreateSharedSwapchainsKHR;
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+PFN_vkCreateXlibSurfaceKHR CreateXlibSurfaceKHR;
+PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR GetPhysicalDeviceXlibPresentationSupportKHR;
+#endif
+#ifdef VK_USE_PLATFORM_XCB_KHR
+PFN_vkCreateXcbSurfaceKHR CreateXcbSurfaceKHR;
+PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR GetPhysicalDeviceXcbPresentationSupportKHR;
+#endif
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+PFN_vkCreateWaylandSurfaceKHR CreateWaylandSurfaceKHR;
+PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR GetPhysicalDeviceWaylandPresentationSupportKHR;
+#endif
+#ifdef VK_USE_PLATFORM_MIR_KHR
+PFN_vkCreateMirSurfaceKHR CreateMirSurfaceKHR;
+PFN_vkGetPhysicalDeviceMirPresentationSupportKHR GetPhysicalDeviceMirPresentationSupportKHR;
+#endif
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+PFN_vkCreateAndroidSurfaceKHR CreateAndroidSurfaceKHR;
+#endif
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+PFN_vkCreateWin32SurfaceKHR CreateWin32SurfaceKHR;
+PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR GetPhysicalDeviceWin32PresentationSupportKHR;
+#endif
+PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallbackEXT;
+PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallbackEXT;
+PFN_vkDebugReportMessageEXT DebugReportMessageEXT;
+
+void init_dispatch_table_top(PFN_vkGetInstanceProcAddr get_instance_proc_addr)
+{
+ GetInstanceProcAddr = get_instance_proc_addr;
+
+ CreateInstance = reinterpret_cast<PFN_vkCreateInstance>(GetInstanceProcAddr(VK_NULL_HANDLE, "vkCreateInstance"));
+ EnumerateInstanceExtensionProperties = reinterpret_cast<PFN_vkEnumerateInstanceExtensionProperties>(GetInstanceProcAddr(VK_NULL_HANDLE, "vkEnumerateInstanceExtensionProperties"));
+ EnumerateInstanceLayerProperties = reinterpret_cast<PFN_vkEnumerateInstanceLayerProperties>(GetInstanceProcAddr(VK_NULL_HANDLE, "vkEnumerateInstanceLayerProperties"));
+}
+
+void init_dispatch_table_middle(VkInstance instance, bool include_bottom)
+{
+ GetInstanceProcAddr = reinterpret_cast<PFN_vkGetInstanceProcAddr>(GetInstanceProcAddr(instance, "vkGetInstanceProcAddr"));
+
+ DestroyInstance = reinterpret_cast<PFN_vkDestroyInstance>(GetInstanceProcAddr(instance, "vkDestroyInstance"));
+ EnumeratePhysicalDevices = reinterpret_cast<PFN_vkEnumeratePhysicalDevices>(GetInstanceProcAddr(instance, "vkEnumeratePhysicalDevices"));
+ GetPhysicalDeviceFeatures = reinterpret_cast<PFN_vkGetPhysicalDeviceFeatures>(GetInstanceProcAddr(instance, "vkGetPhysicalDeviceFeatures"));
+ GetPhysicalDeviceFormatProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceFormatProperties>(GetInstanceProcAddr(instance, "vkGetPhysicalDeviceFormatProperties"));
+ GetPhysicalDeviceImageFormatProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceImageFormatProperties>(GetInstanceProcAddr(instance, "vkGetPhysicalDeviceImageFormatProperties"));
+ GetPhysicalDeviceProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceProperties>(GetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties"));
+ GetPhysicalDeviceQueueFamilyProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceQueueFamilyProperties>(GetInstanceProcAddr(instance, "vkGetPhysicalDeviceQueueFamilyProperties"));
+ GetPhysicalDeviceMemoryProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceMemoryProperties>(GetInstanceProcAddr(instance, "vkGetPhysicalDeviceMemoryProperties"));
+ CreateDevice = reinterpret_cast<PFN_vkCreateDevice>(GetInstanceProcAddr(instance, "vkCreateDevice"));
+ EnumerateDeviceExtensionProperties = reinterpret_cast<PFN_vkEnumerateDeviceExtensionProperties>(GetInstanceProcAddr(instance, "vkEnumerateDeviceExtensionProperties"));
+ EnumerateDeviceLayerProperties = reinterpret_cast<PFN_vkEnumerateDeviceLayerProperties>(GetInstanceProcAddr(instance, "vkEnumerateDeviceLayerProperties"));
+ GetPhysicalDeviceSparseImageFormatProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceSparseImageFormatProperties>(GetInstanceProcAddr(instance, "vkGetPhysicalDeviceSparseImageFormatProperties"));
+ DestroySurfaceKHR = reinterpret_cast<PFN_vkDestroySurfaceKHR>(GetInstanceProcAddr(instance, "vkDestroySurfaceKHR"));
+ GetPhysicalDeviceSurfaceSupportKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceSupportKHR>(GetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceSupportKHR"));
+ GetPhysicalDeviceSurfaceCapabilitiesKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR>(GetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR"));
+ GetPhysicalDeviceSurfaceFormatsKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceFormatsKHR>(GetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceFormatsKHR"));
+ GetPhysicalDeviceSurfacePresentModesKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfacePresentModesKHR>(GetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfacePresentModesKHR"));
+ GetPhysicalDeviceDisplayPropertiesKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceDisplayPropertiesKHR>(GetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPropertiesKHR"));
+ GetPhysicalDeviceDisplayPlanePropertiesKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR>(GetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPlanePropertiesKHR"));
+ GetDisplayPlaneSupportedDisplaysKHR = reinterpret_cast<PFN_vkGetDisplayPlaneSupportedDisplaysKHR>(GetInstanceProcAddr(instance, "vkGetDisplayPlaneSupportedDisplaysKHR"));
+ GetDisplayModePropertiesKHR = reinterpret_cast<PFN_vkGetDisplayModePropertiesKHR>(GetInstanceProcAddr(instance, "vkGetDisplayModePropertiesKHR"));
+ CreateDisplayModeKHR = reinterpret_cast<PFN_vkCreateDisplayModeKHR>(GetInstanceProcAddr(instance, "vkCreateDisplayModeKHR"));
+ GetDisplayPlaneCapabilitiesKHR = reinterpret_cast<PFN_vkGetDisplayPlaneCapabilitiesKHR>(GetInstanceProcAddr(instance, "vkGetDisplayPlaneCapabilitiesKHR"));
+ CreateDisplayPlaneSurfaceKHR = reinterpret_cast<PFN_vkCreateDisplayPlaneSurfaceKHR>(GetInstanceProcAddr(instance, "vkCreateDisplayPlaneSurfaceKHR"));
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+ CreateXlibSurfaceKHR = reinterpret_cast<PFN_vkCreateXlibSurfaceKHR>(GetInstanceProcAddr(instance, "vkCreateXlibSurfaceKHR"));
+#endif
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+ GetPhysicalDeviceXlibPresentationSupportKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR>(GetInstanceProcAddr(instance, "vkGetPhysicalDeviceXlibPresentationSupportKHR"));
+#endif
+#ifdef VK_USE_PLATFORM_XCB_KHR
+ CreateXcbSurfaceKHR = reinterpret_cast<PFN_vkCreateXcbSurfaceKHR>(GetInstanceProcAddr(instance, "vkCreateXcbSurfaceKHR"));
+#endif
+#ifdef VK_USE_PLATFORM_XCB_KHR
+ GetPhysicalDeviceXcbPresentationSupportKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR>(GetInstanceProcAddr(instance, "vkGetPhysicalDeviceXcbPresentationSupportKHR"));
+#endif
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+ CreateWaylandSurfaceKHR = reinterpret_cast<PFN_vkCreateWaylandSurfaceKHR>(GetInstanceProcAddr(instance, "vkCreateWaylandSurfaceKHR"));
+#endif
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+ GetPhysicalDeviceWaylandPresentationSupportKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR>(GetInstanceProcAddr(instance, "vkGetPhysicalDeviceWaylandPresentationSupportKHR"));
+#endif
+#ifdef VK_USE_PLATFORM_MIR_KHR
+ CreateMirSurfaceKHR = reinterpret_cast<PFN_vkCreateMirSurfaceKHR>(GetInstanceProcAddr(instance, "vkCreateMirSurfaceKHR"));
+#endif
+#ifdef VK_USE_PLATFORM_MIR_KHR
+ GetPhysicalDeviceMirPresentationSupportKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceMirPresentationSupportKHR>(GetInstanceProcAddr(instance, "vkGetPhysicalDeviceMirPresentationSupportKHR"));
+#endif
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ CreateAndroidSurfaceKHR = reinterpret_cast<PFN_vkCreateAndroidSurfaceKHR>(GetInstanceProcAddr(instance, "vkCreateAndroidSurfaceKHR"));
+#endif
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ CreateWin32SurfaceKHR = reinterpret_cast<PFN_vkCreateWin32SurfaceKHR>(GetInstanceProcAddr(instance, "vkCreateWin32SurfaceKHR"));
+#endif
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ GetPhysicalDeviceWin32PresentationSupportKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR>(GetInstanceProcAddr(instance, "vkGetPhysicalDeviceWin32PresentationSupportKHR"));
+#endif
+ CreateDebugReportCallbackEXT = reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>(GetInstanceProcAddr(instance, "vkCreateDebugReportCallbackEXT"));
+ DestroyDebugReportCallbackEXT = reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>(GetInstanceProcAddr(instance, "vkDestroyDebugReportCallbackEXT"));
+ DebugReportMessageEXT = reinterpret_cast<PFN_vkDebugReportMessageEXT>(GetInstanceProcAddr(instance, "vkDebugReportMessageEXT"));
+
+ if (!include_bottom)
+ return;
+
+ GetDeviceProcAddr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(GetInstanceProcAddr(instance, "vkGetDeviceProcAddr"));
+ DestroyDevice = reinterpret_cast<PFN_vkDestroyDevice>(GetInstanceProcAddr(instance, "vkDestroyDevice"));
+ GetDeviceQueue = reinterpret_cast<PFN_vkGetDeviceQueue>(GetInstanceProcAddr(instance, "vkGetDeviceQueue"));
+ QueueSubmit = reinterpret_cast<PFN_vkQueueSubmit>(GetInstanceProcAddr(instance, "vkQueueSubmit"));
+ QueueWaitIdle = reinterpret_cast<PFN_vkQueueWaitIdle>(GetInstanceProcAddr(instance, "vkQueueWaitIdle"));
+ DeviceWaitIdle = reinterpret_cast<PFN_vkDeviceWaitIdle>(GetInstanceProcAddr(instance, "vkDeviceWaitIdle"));
+ AllocateMemory = reinterpret_cast<PFN_vkAllocateMemory>(GetInstanceProcAddr(instance, "vkAllocateMemory"));
+ FreeMemory = reinterpret_cast<PFN_vkFreeMemory>(GetInstanceProcAddr(instance, "vkFreeMemory"));
+ MapMemory = reinterpret_cast<PFN_vkMapMemory>(GetInstanceProcAddr(instance, "vkMapMemory"));
+ UnmapMemory = reinterpret_cast<PFN_vkUnmapMemory>(GetInstanceProcAddr(instance, "vkUnmapMemory"));
+ FlushMappedMemoryRanges = reinterpret_cast<PFN_vkFlushMappedMemoryRanges>(GetInstanceProcAddr(instance, "vkFlushMappedMemoryRanges"));
+ InvalidateMappedMemoryRanges = reinterpret_cast<PFN_vkInvalidateMappedMemoryRanges>(GetInstanceProcAddr(instance, "vkInvalidateMappedMemoryRanges"));
+ GetDeviceMemoryCommitment = reinterpret_cast<PFN_vkGetDeviceMemoryCommitment>(GetInstanceProcAddr(instance, "vkGetDeviceMemoryCommitment"));
+ BindBufferMemory = reinterpret_cast<PFN_vkBindBufferMemory>(GetInstanceProcAddr(instance, "vkBindBufferMemory"));
+ BindImageMemory = reinterpret_cast<PFN_vkBindImageMemory>(GetInstanceProcAddr(instance, "vkBindImageMemory"));
+ GetBufferMemoryRequirements = reinterpret_cast<PFN_vkGetBufferMemoryRequirements>(GetInstanceProcAddr(instance, "vkGetBufferMemoryRequirements"));
+ GetImageMemoryRequirements = reinterpret_cast<PFN_vkGetImageMemoryRequirements>(GetInstanceProcAddr(instance, "vkGetImageMemoryRequirements"));
+ GetImageSparseMemoryRequirements = reinterpret_cast<PFN_vkGetImageSparseMemoryRequirements>(GetInstanceProcAddr(instance, "vkGetImageSparseMemoryRequirements"));
+ QueueBindSparse = reinterpret_cast<PFN_vkQueueBindSparse>(GetInstanceProcAddr(instance, "vkQueueBindSparse"));
+ CreateFence = reinterpret_cast<PFN_vkCreateFence>(GetInstanceProcAddr(instance, "vkCreateFence"));
+ DestroyFence = reinterpret_cast<PFN_vkDestroyFence>(GetInstanceProcAddr(instance, "vkDestroyFence"));
+ ResetFences = reinterpret_cast<PFN_vkResetFences>(GetInstanceProcAddr(instance, "vkResetFences"));
+ GetFenceStatus = reinterpret_cast<PFN_vkGetFenceStatus>(GetInstanceProcAddr(instance, "vkGetFenceStatus"));
+ WaitForFences = reinterpret_cast<PFN_vkWaitForFences>(GetInstanceProcAddr(instance, "vkWaitForFences"));
+ CreateSemaphore = reinterpret_cast<PFN_vkCreateSemaphore>(GetInstanceProcAddr(instance, "vkCreateSemaphore"));
+ DestroySemaphore = reinterpret_cast<PFN_vkDestroySemaphore>(GetInstanceProcAddr(instance, "vkDestroySemaphore"));
+ CreateEvent = reinterpret_cast<PFN_vkCreateEvent>(GetInstanceProcAddr(instance, "vkCreateEvent"));
+ DestroyEvent = reinterpret_cast<PFN_vkDestroyEvent>(GetInstanceProcAddr(instance, "vkDestroyEvent"));
+ GetEventStatus = reinterpret_cast<PFN_vkGetEventStatus>(GetInstanceProcAddr(instance, "vkGetEventStatus"));
+ SetEvent = reinterpret_cast<PFN_vkSetEvent>(GetInstanceProcAddr(instance, "vkSetEvent"));
+ ResetEvent = reinterpret_cast<PFN_vkResetEvent>(GetInstanceProcAddr(instance, "vkResetEvent"));
+ CreateQueryPool = reinterpret_cast<PFN_vkCreateQueryPool>(GetInstanceProcAddr(instance, "vkCreateQueryPool"));
+ DestroyQueryPool = reinterpret_cast<PFN_vkDestroyQueryPool>(GetInstanceProcAddr(instance, "vkDestroyQueryPool"));
+ GetQueryPoolResults = reinterpret_cast<PFN_vkGetQueryPoolResults>(GetInstanceProcAddr(instance, "vkGetQueryPoolResults"));
+ CreateBuffer = reinterpret_cast<PFN_vkCreateBuffer>(GetInstanceProcAddr(instance, "vkCreateBuffer"));
+ DestroyBuffer = reinterpret_cast<PFN_vkDestroyBuffer>(GetInstanceProcAddr(instance, "vkDestroyBuffer"));
+ CreateBufferView = reinterpret_cast<PFN_vkCreateBufferView>(GetInstanceProcAddr(instance, "vkCreateBufferView"));
+ DestroyBufferView = reinterpret_cast<PFN_vkDestroyBufferView>(GetInstanceProcAddr(instance, "vkDestroyBufferView"));
+ CreateImage = reinterpret_cast<PFN_vkCreateImage>(GetInstanceProcAddr(instance, "vkCreateImage"));
+ DestroyImage = reinterpret_cast<PFN_vkDestroyImage>(GetInstanceProcAddr(instance, "vkDestroyImage"));
+ GetImageSubresourceLayout = reinterpret_cast<PFN_vkGetImageSubresourceLayout>(GetInstanceProcAddr(instance, "vkGetImageSubresourceLayout"));
+ CreateImageView = reinterpret_cast<PFN_vkCreateImageView>(GetInstanceProcAddr(instance, "vkCreateImageView"));
+ DestroyImageView = reinterpret_cast<PFN_vkDestroyImageView>(GetInstanceProcAddr(instance, "vkDestroyImageView"));
+ CreateShaderModule = reinterpret_cast<PFN_vkCreateShaderModule>(GetInstanceProcAddr(instance, "vkCreateShaderModule"));
+ DestroyShaderModule = reinterpret_cast<PFN_vkDestroyShaderModule>(GetInstanceProcAddr(instance, "vkDestroyShaderModule"));
+ CreatePipelineCache = reinterpret_cast<PFN_vkCreatePipelineCache>(GetInstanceProcAddr(instance, "vkCreatePipelineCache"));
+ DestroyPipelineCache = reinterpret_cast<PFN_vkDestroyPipelineCache>(GetInstanceProcAddr(instance, "vkDestroyPipelineCache"));
+ GetPipelineCacheData = reinterpret_cast<PFN_vkGetPipelineCacheData>(GetInstanceProcAddr(instance, "vkGetPipelineCacheData"));
+ MergePipelineCaches = reinterpret_cast<PFN_vkMergePipelineCaches>(GetInstanceProcAddr(instance, "vkMergePipelineCaches"));
+ CreateGraphicsPipelines = reinterpret_cast<PFN_vkCreateGraphicsPipelines>(GetInstanceProcAddr(instance, "vkCreateGraphicsPipelines"));
+ CreateComputePipelines = reinterpret_cast<PFN_vkCreateComputePipelines>(GetInstanceProcAddr(instance, "vkCreateComputePipelines"));
+ DestroyPipeline = reinterpret_cast<PFN_vkDestroyPipeline>(GetInstanceProcAddr(instance, "vkDestroyPipeline"));
+ CreatePipelineLayout = reinterpret_cast<PFN_vkCreatePipelineLayout>(GetInstanceProcAddr(instance, "vkCreatePipelineLayout"));
+ DestroyPipelineLayout = reinterpret_cast<PFN_vkDestroyPipelineLayout>(GetInstanceProcAddr(instance, "vkDestroyPipelineLayout"));
+ CreateSampler = reinterpret_cast<PFN_vkCreateSampler>(GetInstanceProcAddr(instance, "vkCreateSampler"));
+ DestroySampler = reinterpret_cast<PFN_vkDestroySampler>(GetInstanceProcAddr(instance, "vkDestroySampler"));
+ CreateDescriptorSetLayout = reinterpret_cast<PFN_vkCreateDescriptorSetLayout>(GetInstanceProcAddr(instance, "vkCreateDescriptorSetLayout"));
+ DestroyDescriptorSetLayout = reinterpret_cast<PFN_vkDestroyDescriptorSetLayout>(GetInstanceProcAddr(instance, "vkDestroyDescriptorSetLayout"));
+ CreateDescriptorPool = reinterpret_cast<PFN_vkCreateDescriptorPool>(GetInstanceProcAddr(instance, "vkCreateDescriptorPool"));
+ DestroyDescriptorPool = reinterpret_cast<PFN_vkDestroyDescriptorPool>(GetInstanceProcAddr(instance, "vkDestroyDescriptorPool"));
+ ResetDescriptorPool = reinterpret_cast<PFN_vkResetDescriptorPool>(GetInstanceProcAddr(instance, "vkResetDescriptorPool"));
+ AllocateDescriptorSets = reinterpret_cast<PFN_vkAllocateDescriptorSets>(GetInstanceProcAddr(instance, "vkAllocateDescriptorSets"));
+ FreeDescriptorSets = reinterpret_cast<PFN_vkFreeDescriptorSets>(GetInstanceProcAddr(instance, "vkFreeDescriptorSets"));
+ UpdateDescriptorSets = reinterpret_cast<PFN_vkUpdateDescriptorSets>(GetInstanceProcAddr(instance, "vkUpdateDescriptorSets"));
+ CreateFramebuffer = reinterpret_cast<PFN_vkCreateFramebuffer>(GetInstanceProcAddr(instance, "vkCreateFramebuffer"));
+ DestroyFramebuffer = reinterpret_cast<PFN_vkDestroyFramebuffer>(GetInstanceProcAddr(instance, "vkDestroyFramebuffer"));
+ CreateRenderPass = reinterpret_cast<PFN_vkCreateRenderPass>(GetInstanceProcAddr(instance, "vkCreateRenderPass"));
+ DestroyRenderPass = reinterpret_cast<PFN_vkDestroyRenderPass>(GetInstanceProcAddr(instance, "vkDestroyRenderPass"));
+ GetRenderAreaGranularity = reinterpret_cast<PFN_vkGetRenderAreaGranularity>(GetInstanceProcAddr(instance, "vkGetRenderAreaGranularity"));
+ CreateCommandPool = reinterpret_cast<PFN_vkCreateCommandPool>(GetInstanceProcAddr(instance, "vkCreateCommandPool"));
+ DestroyCommandPool = reinterpret_cast<PFN_vkDestroyCommandPool>(GetInstanceProcAddr(instance, "vkDestroyCommandPool"));
+ ResetCommandPool = reinterpret_cast<PFN_vkResetCommandPool>(GetInstanceProcAddr(instance, "vkResetCommandPool"));
+ AllocateCommandBuffers = reinterpret_cast<PFN_vkAllocateCommandBuffers>(GetInstanceProcAddr(instance, "vkAllocateCommandBuffers"));
+ FreeCommandBuffers = reinterpret_cast<PFN_vkFreeCommandBuffers>(GetInstanceProcAddr(instance, "vkFreeCommandBuffers"));
+ BeginCommandBuffer = reinterpret_cast<PFN_vkBeginCommandBuffer>(GetInstanceProcAddr(instance, "vkBeginCommandBuffer"));
+ EndCommandBuffer = reinterpret_cast<PFN_vkEndCommandBuffer>(GetInstanceProcAddr(instance, "vkEndCommandBuffer"));
+ ResetCommandBuffer = reinterpret_cast<PFN_vkResetCommandBuffer>(GetInstanceProcAddr(instance, "vkResetCommandBuffer"));
+ CmdBindPipeline = reinterpret_cast<PFN_vkCmdBindPipeline>(GetInstanceProcAddr(instance, "vkCmdBindPipeline"));
+ CmdSetViewport = reinterpret_cast<PFN_vkCmdSetViewport>(GetInstanceProcAddr(instance, "vkCmdSetViewport"));
+ CmdSetScissor = reinterpret_cast<PFN_vkCmdSetScissor>(GetInstanceProcAddr(instance, "vkCmdSetScissor"));
+ CmdSetLineWidth = reinterpret_cast<PFN_vkCmdSetLineWidth>(GetInstanceProcAddr(instance, "vkCmdSetLineWidth"));
+ CmdSetDepthBias = reinterpret_cast<PFN_vkCmdSetDepthBias>(GetInstanceProcAddr(instance, "vkCmdSetDepthBias"));
+ CmdSetBlendConstants = reinterpret_cast<PFN_vkCmdSetBlendConstants>(GetInstanceProcAddr(instance, "vkCmdSetBlendConstants"));
+ CmdSetDepthBounds = reinterpret_cast<PFN_vkCmdSetDepthBounds>(GetInstanceProcAddr(instance, "vkCmdSetDepthBounds"));
+ CmdSetStencilCompareMask = reinterpret_cast<PFN_vkCmdSetStencilCompareMask>(GetInstanceProcAddr(instance, "vkCmdSetStencilCompareMask"));
+ CmdSetStencilWriteMask = reinterpret_cast<PFN_vkCmdSetStencilWriteMask>(GetInstanceProcAddr(instance, "vkCmdSetStencilWriteMask"));
+ CmdSetStencilReference = reinterpret_cast<PFN_vkCmdSetStencilReference>(GetInstanceProcAddr(instance, "vkCmdSetStencilReference"));
+ CmdBindDescriptorSets = reinterpret_cast<PFN_vkCmdBindDescriptorSets>(GetInstanceProcAddr(instance, "vkCmdBindDescriptorSets"));
+ CmdBindIndexBuffer = reinterpret_cast<PFN_vkCmdBindIndexBuffer>(GetInstanceProcAddr(instance, "vkCmdBindIndexBuffer"));
+ CmdBindVertexBuffers = reinterpret_cast<PFN_vkCmdBindVertexBuffers>(GetInstanceProcAddr(instance, "vkCmdBindVertexBuffers"));
+ CmdDraw = reinterpret_cast<PFN_vkCmdDraw>(GetInstanceProcAddr(instance, "vkCmdDraw"));
+ CmdDrawIndexed = reinterpret_cast<PFN_vkCmdDrawIndexed>(GetInstanceProcAddr(instance, "vkCmdDrawIndexed"));
+ CmdDrawIndirect = reinterpret_cast<PFN_vkCmdDrawIndirect>(GetInstanceProcAddr(instance, "vkCmdDrawIndirect"));
+ CmdDrawIndexedIndirect = reinterpret_cast<PFN_vkCmdDrawIndexedIndirect>(GetInstanceProcAddr(instance, "vkCmdDrawIndexedIndirect"));
+ CmdDispatch = reinterpret_cast<PFN_vkCmdDispatch>(GetInstanceProcAddr(instance, "vkCmdDispatch"));
+ CmdDispatchIndirect = reinterpret_cast<PFN_vkCmdDispatchIndirect>(GetInstanceProcAddr(instance, "vkCmdDispatchIndirect"));
+ CmdCopyBuffer = reinterpret_cast<PFN_vkCmdCopyBuffer>(GetInstanceProcAddr(instance, "vkCmdCopyBuffer"));
+ CmdCopyImage = reinterpret_cast<PFN_vkCmdCopyImage>(GetInstanceProcAddr(instance, "vkCmdCopyImage"));
+ CmdBlitImage = reinterpret_cast<PFN_vkCmdBlitImage>(GetInstanceProcAddr(instance, "vkCmdBlitImage"));
+ CmdCopyBufferToImage = reinterpret_cast<PFN_vkCmdCopyBufferToImage>(GetInstanceProcAddr(instance, "vkCmdCopyBufferToImage"));
+ CmdCopyImageToBuffer = reinterpret_cast<PFN_vkCmdCopyImageToBuffer>(GetInstanceProcAddr(instance, "vkCmdCopyImageToBuffer"));
+ CmdUpdateBuffer = reinterpret_cast<PFN_vkCmdUpdateBuffer>(GetInstanceProcAddr(instance, "vkCmdUpdateBuffer"));
+ CmdFillBuffer = reinterpret_cast<PFN_vkCmdFillBuffer>(GetInstanceProcAddr(instance, "vkCmdFillBuffer"));
+ CmdClearColorImage = reinterpret_cast<PFN_vkCmdClearColorImage>(GetInstanceProcAddr(instance, "vkCmdClearColorImage"));
+ CmdClearDepthStencilImage = reinterpret_cast<PFN_vkCmdClearDepthStencilImage>(GetInstanceProcAddr(instance, "vkCmdClearDepthStencilImage"));
+ CmdClearAttachments = reinterpret_cast<PFN_vkCmdClearAttachments>(GetInstanceProcAddr(instance, "vkCmdClearAttachments"));
+ CmdResolveImage = reinterpret_cast<PFN_vkCmdResolveImage>(GetInstanceProcAddr(instance, "vkCmdResolveImage"));
+ CmdSetEvent = reinterpret_cast<PFN_vkCmdSetEvent>(GetInstanceProcAddr(instance, "vkCmdSetEvent"));
+ CmdResetEvent = reinterpret_cast<PFN_vkCmdResetEvent>(GetInstanceProcAddr(instance, "vkCmdResetEvent"));
+ CmdWaitEvents = reinterpret_cast<PFN_vkCmdWaitEvents>(GetInstanceProcAddr(instance, "vkCmdWaitEvents"));
+ CmdPipelineBarrier = reinterpret_cast<PFN_vkCmdPipelineBarrier>(GetInstanceProcAddr(instance, "vkCmdPipelineBarrier"));
+ CmdBeginQuery = reinterpret_cast<PFN_vkCmdBeginQuery>(GetInstanceProcAddr(instance, "vkCmdBeginQuery"));
+ CmdEndQuery = reinterpret_cast<PFN_vkCmdEndQuery>(GetInstanceProcAddr(instance, "vkCmdEndQuery"));
+ CmdResetQueryPool = reinterpret_cast<PFN_vkCmdResetQueryPool>(GetInstanceProcAddr(instance, "vkCmdResetQueryPool"));
+ CmdWriteTimestamp = reinterpret_cast<PFN_vkCmdWriteTimestamp>(GetInstanceProcAddr(instance, "vkCmdWriteTimestamp"));
+ CmdCopyQueryPoolResults = reinterpret_cast<PFN_vkCmdCopyQueryPoolResults>(GetInstanceProcAddr(instance, "vkCmdCopyQueryPoolResults"));
+ CmdPushConstants = reinterpret_cast<PFN_vkCmdPushConstants>(GetInstanceProcAddr(instance, "vkCmdPushConstants"));
+ CmdBeginRenderPass = reinterpret_cast<PFN_vkCmdBeginRenderPass>(GetInstanceProcAddr(instance, "vkCmdBeginRenderPass"));
+ CmdNextSubpass = reinterpret_cast<PFN_vkCmdNextSubpass>(GetInstanceProcAddr(instance, "vkCmdNextSubpass"));
+ CmdEndRenderPass = reinterpret_cast<PFN_vkCmdEndRenderPass>(GetInstanceProcAddr(instance, "vkCmdEndRenderPass"));
+ CmdExecuteCommands = reinterpret_cast<PFN_vkCmdExecuteCommands>(GetInstanceProcAddr(instance, "vkCmdExecuteCommands"));
+ CreateSwapchainKHR = reinterpret_cast<PFN_vkCreateSwapchainKHR>(GetInstanceProcAddr(instance, "vkCreateSwapchainKHR"));
+ DestroySwapchainKHR = reinterpret_cast<PFN_vkDestroySwapchainKHR>(GetInstanceProcAddr(instance, "vkDestroySwapchainKHR"));
+ GetSwapchainImagesKHR = reinterpret_cast<PFN_vkGetSwapchainImagesKHR>(GetInstanceProcAddr(instance, "vkGetSwapchainImagesKHR"));
+ AcquireNextImageKHR = reinterpret_cast<PFN_vkAcquireNextImageKHR>(GetInstanceProcAddr(instance, "vkAcquireNextImageKHR"));
+ QueuePresentKHR = reinterpret_cast<PFN_vkQueuePresentKHR>(GetInstanceProcAddr(instance, "vkQueuePresentKHR"));
+ CreateSharedSwapchainsKHR = reinterpret_cast<PFN_vkCreateSharedSwapchainsKHR>(GetInstanceProcAddr(instance, "vkCreateSharedSwapchainsKHR"));
+}
+
+void init_dispatch_table_bottom(VkInstance instance, VkDevice dev)
+{
+ GetDeviceProcAddr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(GetInstanceProcAddr(instance, "vkGetDeviceProcAddr"));
+ GetDeviceProcAddr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(GetDeviceProcAddr(dev, "vkGetDeviceProcAddr"));
+
+ DestroyDevice = reinterpret_cast<PFN_vkDestroyDevice>(GetDeviceProcAddr(dev, "vkDestroyDevice"));
+ GetDeviceQueue = reinterpret_cast<PFN_vkGetDeviceQueue>(GetDeviceProcAddr(dev, "vkGetDeviceQueue"));
+ QueueSubmit = reinterpret_cast<PFN_vkQueueSubmit>(GetDeviceProcAddr(dev, "vkQueueSubmit"));
+ QueueWaitIdle = reinterpret_cast<PFN_vkQueueWaitIdle>(GetDeviceProcAddr(dev, "vkQueueWaitIdle"));
+ DeviceWaitIdle = reinterpret_cast<PFN_vkDeviceWaitIdle>(GetDeviceProcAddr(dev, "vkDeviceWaitIdle"));
+ AllocateMemory = reinterpret_cast<PFN_vkAllocateMemory>(GetDeviceProcAddr(dev, "vkAllocateMemory"));
+ FreeMemory = reinterpret_cast<PFN_vkFreeMemory>(GetDeviceProcAddr(dev, "vkFreeMemory"));
+ MapMemory = reinterpret_cast<PFN_vkMapMemory>(GetDeviceProcAddr(dev, "vkMapMemory"));
+ UnmapMemory = reinterpret_cast<PFN_vkUnmapMemory>(GetDeviceProcAddr(dev, "vkUnmapMemory"));
+ FlushMappedMemoryRanges = reinterpret_cast<PFN_vkFlushMappedMemoryRanges>(GetDeviceProcAddr(dev, "vkFlushMappedMemoryRanges"));
+ InvalidateMappedMemoryRanges = reinterpret_cast<PFN_vkInvalidateMappedMemoryRanges>(GetDeviceProcAddr(dev, "vkInvalidateMappedMemoryRanges"));
+ GetDeviceMemoryCommitment = reinterpret_cast<PFN_vkGetDeviceMemoryCommitment>(GetDeviceProcAddr(dev, "vkGetDeviceMemoryCommitment"));
+ BindBufferMemory = reinterpret_cast<PFN_vkBindBufferMemory>(GetDeviceProcAddr(dev, "vkBindBufferMemory"));
+ BindImageMemory = reinterpret_cast<PFN_vkBindImageMemory>(GetDeviceProcAddr(dev, "vkBindImageMemory"));
+ GetBufferMemoryRequirements = reinterpret_cast<PFN_vkGetBufferMemoryRequirements>(GetDeviceProcAddr(dev, "vkGetBufferMemoryRequirements"));
+ GetImageMemoryRequirements = reinterpret_cast<PFN_vkGetImageMemoryRequirements>(GetDeviceProcAddr(dev, "vkGetImageMemoryRequirements"));
+ GetImageSparseMemoryRequirements = reinterpret_cast<PFN_vkGetImageSparseMemoryRequirements>(GetDeviceProcAddr(dev, "vkGetImageSparseMemoryRequirements"));
+ QueueBindSparse = reinterpret_cast<PFN_vkQueueBindSparse>(GetDeviceProcAddr(dev, "vkQueueBindSparse"));
+ CreateFence = reinterpret_cast<PFN_vkCreateFence>(GetDeviceProcAddr(dev, "vkCreateFence"));
+ DestroyFence = reinterpret_cast<PFN_vkDestroyFence>(GetDeviceProcAddr(dev, "vkDestroyFence"));
+ ResetFences = reinterpret_cast<PFN_vkResetFences>(GetDeviceProcAddr(dev, "vkResetFences"));
+ GetFenceStatus = reinterpret_cast<PFN_vkGetFenceStatus>(GetDeviceProcAddr(dev, "vkGetFenceStatus"));
+ WaitForFences = reinterpret_cast<PFN_vkWaitForFences>(GetDeviceProcAddr(dev, "vkWaitForFences"));
+ CreateSemaphore = reinterpret_cast<PFN_vkCreateSemaphore>(GetDeviceProcAddr(dev, "vkCreateSemaphore"));
+ DestroySemaphore = reinterpret_cast<PFN_vkDestroySemaphore>(GetDeviceProcAddr(dev, "vkDestroySemaphore"));
+ CreateEvent = reinterpret_cast<PFN_vkCreateEvent>(GetDeviceProcAddr(dev, "vkCreateEvent"));
+ DestroyEvent = reinterpret_cast<PFN_vkDestroyEvent>(GetDeviceProcAddr(dev, "vkDestroyEvent"));
+ GetEventStatus = reinterpret_cast<PFN_vkGetEventStatus>(GetDeviceProcAddr(dev, "vkGetEventStatus"));
+ SetEvent = reinterpret_cast<PFN_vkSetEvent>(GetDeviceProcAddr(dev, "vkSetEvent"));
+ ResetEvent = reinterpret_cast<PFN_vkResetEvent>(GetDeviceProcAddr(dev, "vkResetEvent"));
+ CreateQueryPool = reinterpret_cast<PFN_vkCreateQueryPool>(GetDeviceProcAddr(dev, "vkCreateQueryPool"));
+ DestroyQueryPool = reinterpret_cast<PFN_vkDestroyQueryPool>(GetDeviceProcAddr(dev, "vkDestroyQueryPool"));
+ GetQueryPoolResults = reinterpret_cast<PFN_vkGetQueryPoolResults>(GetDeviceProcAddr(dev, "vkGetQueryPoolResults"));
+ CreateBuffer = reinterpret_cast<PFN_vkCreateBuffer>(GetDeviceProcAddr(dev, "vkCreateBuffer"));
+ DestroyBuffer = reinterpret_cast<PFN_vkDestroyBuffer>(GetDeviceProcAddr(dev, "vkDestroyBuffer"));
+ CreateBufferView = reinterpret_cast<PFN_vkCreateBufferView>(GetDeviceProcAddr(dev, "vkCreateBufferView"));
+ DestroyBufferView = reinterpret_cast<PFN_vkDestroyBufferView>(GetDeviceProcAddr(dev, "vkDestroyBufferView"));
+ CreateImage = reinterpret_cast<PFN_vkCreateImage>(GetDeviceProcAddr(dev, "vkCreateImage"));
+ DestroyImage = reinterpret_cast<PFN_vkDestroyImage>(GetDeviceProcAddr(dev, "vkDestroyImage"));
+ GetImageSubresourceLayout = reinterpret_cast<PFN_vkGetImageSubresourceLayout>(GetDeviceProcAddr(dev, "vkGetImageSubresourceLayout"));
+ CreateImageView = reinterpret_cast<PFN_vkCreateImageView>(GetDeviceProcAddr(dev, "vkCreateImageView"));
+ DestroyImageView = reinterpret_cast<PFN_vkDestroyImageView>(GetDeviceProcAddr(dev, "vkDestroyImageView"));
+ CreateShaderModule = reinterpret_cast<PFN_vkCreateShaderModule>(GetDeviceProcAddr(dev, "vkCreateShaderModule"));
+ DestroyShaderModule = reinterpret_cast<PFN_vkDestroyShaderModule>(GetDeviceProcAddr(dev, "vkDestroyShaderModule"));
+ CreatePipelineCache = reinterpret_cast<PFN_vkCreatePipelineCache>(GetDeviceProcAddr(dev, "vkCreatePipelineCache"));
+ DestroyPipelineCache = reinterpret_cast<PFN_vkDestroyPipelineCache>(GetDeviceProcAddr(dev, "vkDestroyPipelineCache"));
+ GetPipelineCacheData = reinterpret_cast<PFN_vkGetPipelineCacheData>(GetDeviceProcAddr(dev, "vkGetPipelineCacheData"));
+ MergePipelineCaches = reinterpret_cast<PFN_vkMergePipelineCaches>(GetDeviceProcAddr(dev, "vkMergePipelineCaches"));
+ CreateGraphicsPipelines = reinterpret_cast<PFN_vkCreateGraphicsPipelines>(GetDeviceProcAddr(dev, "vkCreateGraphicsPipelines"));
+ CreateComputePipelines = reinterpret_cast<PFN_vkCreateComputePipelines>(GetDeviceProcAddr(dev, "vkCreateComputePipelines"));
+ DestroyPipeline = reinterpret_cast<PFN_vkDestroyPipeline>(GetDeviceProcAddr(dev, "vkDestroyPipeline"));
+ CreatePipelineLayout = reinterpret_cast<PFN_vkCreatePipelineLayout>(GetDeviceProcAddr(dev, "vkCreatePipelineLayout"));
+ DestroyPipelineLayout = reinterpret_cast<PFN_vkDestroyPipelineLayout>(GetDeviceProcAddr(dev, "vkDestroyPipelineLayout"));
+ CreateSampler = reinterpret_cast<PFN_vkCreateSampler>(GetDeviceProcAddr(dev, "vkCreateSampler"));
+ DestroySampler = reinterpret_cast<PFN_vkDestroySampler>(GetDeviceProcAddr(dev, "vkDestroySampler"));
+ CreateDescriptorSetLayout = reinterpret_cast<PFN_vkCreateDescriptorSetLayout>(GetDeviceProcAddr(dev, "vkCreateDescriptorSetLayout"));
+ DestroyDescriptorSetLayout = reinterpret_cast<PFN_vkDestroyDescriptorSetLayout>(GetDeviceProcAddr(dev, "vkDestroyDescriptorSetLayout"));
+ CreateDescriptorPool = reinterpret_cast<PFN_vkCreateDescriptorPool>(GetDeviceProcAddr(dev, "vkCreateDescriptorPool"));
+ DestroyDescriptorPool = reinterpret_cast<PFN_vkDestroyDescriptorPool>(GetDeviceProcAddr(dev, "vkDestroyDescriptorPool"));
+ ResetDescriptorPool = reinterpret_cast<PFN_vkResetDescriptorPool>(GetDeviceProcAddr(dev, "vkResetDescriptorPool"));
+ AllocateDescriptorSets = reinterpret_cast<PFN_vkAllocateDescriptorSets>(GetDeviceProcAddr(dev, "vkAllocateDescriptorSets"));
+ FreeDescriptorSets = reinterpret_cast<PFN_vkFreeDescriptorSets>(GetDeviceProcAddr(dev, "vkFreeDescriptorSets"));
+ UpdateDescriptorSets = reinterpret_cast<PFN_vkUpdateDescriptorSets>(GetDeviceProcAddr(dev, "vkUpdateDescriptorSets"));
+ CreateFramebuffer = reinterpret_cast<PFN_vkCreateFramebuffer>(GetDeviceProcAddr(dev, "vkCreateFramebuffer"));
+ DestroyFramebuffer = reinterpret_cast<PFN_vkDestroyFramebuffer>(GetDeviceProcAddr(dev, "vkDestroyFramebuffer"));
+ CreateRenderPass = reinterpret_cast<PFN_vkCreateRenderPass>(GetDeviceProcAddr(dev, "vkCreateRenderPass"));
+ DestroyRenderPass = reinterpret_cast<PFN_vkDestroyRenderPass>(GetDeviceProcAddr(dev, "vkDestroyRenderPass"));
+ GetRenderAreaGranularity = reinterpret_cast<PFN_vkGetRenderAreaGranularity>(GetDeviceProcAddr(dev, "vkGetRenderAreaGranularity"));
+ CreateCommandPool = reinterpret_cast<PFN_vkCreateCommandPool>(GetDeviceProcAddr(dev, "vkCreateCommandPool"));
+ DestroyCommandPool = reinterpret_cast<PFN_vkDestroyCommandPool>(GetDeviceProcAddr(dev, "vkDestroyCommandPool"));
+ ResetCommandPool = reinterpret_cast<PFN_vkResetCommandPool>(GetDeviceProcAddr(dev, "vkResetCommandPool"));
+ AllocateCommandBuffers = reinterpret_cast<PFN_vkAllocateCommandBuffers>(GetDeviceProcAddr(dev, "vkAllocateCommandBuffers"));
+ FreeCommandBuffers = reinterpret_cast<PFN_vkFreeCommandBuffers>(GetDeviceProcAddr(dev, "vkFreeCommandBuffers"));
+ BeginCommandBuffer = reinterpret_cast<PFN_vkBeginCommandBuffer>(GetDeviceProcAddr(dev, "vkBeginCommandBuffer"));
+ EndCommandBuffer = reinterpret_cast<PFN_vkEndCommandBuffer>(GetDeviceProcAddr(dev, "vkEndCommandBuffer"));
+ ResetCommandBuffer = reinterpret_cast<PFN_vkResetCommandBuffer>(GetDeviceProcAddr(dev, "vkResetCommandBuffer"));
+ CmdBindPipeline = reinterpret_cast<PFN_vkCmdBindPipeline>(GetDeviceProcAddr(dev, "vkCmdBindPipeline"));
+ CmdSetViewport = reinterpret_cast<PFN_vkCmdSetViewport>(GetDeviceProcAddr(dev, "vkCmdSetViewport"));
+ CmdSetScissor = reinterpret_cast<PFN_vkCmdSetScissor>(GetDeviceProcAddr(dev, "vkCmdSetScissor"));
+ CmdSetLineWidth = reinterpret_cast<PFN_vkCmdSetLineWidth>(GetDeviceProcAddr(dev, "vkCmdSetLineWidth"));
+ CmdSetDepthBias = reinterpret_cast<PFN_vkCmdSetDepthBias>(GetDeviceProcAddr(dev, "vkCmdSetDepthBias"));
+ CmdSetBlendConstants = reinterpret_cast<PFN_vkCmdSetBlendConstants>(GetDeviceProcAddr(dev, "vkCmdSetBlendConstants"));
+ CmdSetDepthBounds = reinterpret_cast<PFN_vkCmdSetDepthBounds>(GetDeviceProcAddr(dev, "vkCmdSetDepthBounds"));
+ CmdSetStencilCompareMask = reinterpret_cast<PFN_vkCmdSetStencilCompareMask>(GetDeviceProcAddr(dev, "vkCmdSetStencilCompareMask"));
+ CmdSetStencilWriteMask = reinterpret_cast<PFN_vkCmdSetStencilWriteMask>(GetDeviceProcAddr(dev, "vkCmdSetStencilWriteMask"));
+ CmdSetStencilReference = reinterpret_cast<PFN_vkCmdSetStencilReference>(GetDeviceProcAddr(dev, "vkCmdSetStencilReference"));
+ CmdBindDescriptorSets = reinterpret_cast<PFN_vkCmdBindDescriptorSets>(GetDeviceProcAddr(dev, "vkCmdBindDescriptorSets"));
+ CmdBindIndexBuffer = reinterpret_cast<PFN_vkCmdBindIndexBuffer>(GetDeviceProcAddr(dev, "vkCmdBindIndexBuffer"));
+ CmdBindVertexBuffers = reinterpret_cast<PFN_vkCmdBindVertexBuffers>(GetDeviceProcAddr(dev, "vkCmdBindVertexBuffers"));
+ CmdDraw = reinterpret_cast<PFN_vkCmdDraw>(GetDeviceProcAddr(dev, "vkCmdDraw"));
+ CmdDrawIndexed = reinterpret_cast<PFN_vkCmdDrawIndexed>(GetDeviceProcAddr(dev, "vkCmdDrawIndexed"));
+ CmdDrawIndirect = reinterpret_cast<PFN_vkCmdDrawIndirect>(GetDeviceProcAddr(dev, "vkCmdDrawIndirect"));
+ CmdDrawIndexedIndirect = reinterpret_cast<PFN_vkCmdDrawIndexedIndirect>(GetDeviceProcAddr(dev, "vkCmdDrawIndexedIndirect"));
+ CmdDispatch = reinterpret_cast<PFN_vkCmdDispatch>(GetDeviceProcAddr(dev, "vkCmdDispatch"));
+ CmdDispatchIndirect = reinterpret_cast<PFN_vkCmdDispatchIndirect>(GetDeviceProcAddr(dev, "vkCmdDispatchIndirect"));
+ CmdCopyBuffer = reinterpret_cast<PFN_vkCmdCopyBuffer>(GetDeviceProcAddr(dev, "vkCmdCopyBuffer"));
+ CmdCopyImage = reinterpret_cast<PFN_vkCmdCopyImage>(GetDeviceProcAddr(dev, "vkCmdCopyImage"));
+ CmdBlitImage = reinterpret_cast<PFN_vkCmdBlitImage>(GetDeviceProcAddr(dev, "vkCmdBlitImage"));
+ CmdCopyBufferToImage = reinterpret_cast<PFN_vkCmdCopyBufferToImage>(GetDeviceProcAddr(dev, "vkCmdCopyBufferToImage"));
+ CmdCopyImageToBuffer = reinterpret_cast<PFN_vkCmdCopyImageToBuffer>(GetDeviceProcAddr(dev, "vkCmdCopyImageToBuffer"));
+ CmdUpdateBuffer = reinterpret_cast<PFN_vkCmdUpdateBuffer>(GetDeviceProcAddr(dev, "vkCmdUpdateBuffer"));
+ CmdFillBuffer = reinterpret_cast<PFN_vkCmdFillBuffer>(GetDeviceProcAddr(dev, "vkCmdFillBuffer"));
+ CmdClearColorImage = reinterpret_cast<PFN_vkCmdClearColorImage>(GetDeviceProcAddr(dev, "vkCmdClearColorImage"));
+ CmdClearDepthStencilImage = reinterpret_cast<PFN_vkCmdClearDepthStencilImage>(GetDeviceProcAddr(dev, "vkCmdClearDepthStencilImage"));
+ CmdClearAttachments = reinterpret_cast<PFN_vkCmdClearAttachments>(GetDeviceProcAddr(dev, "vkCmdClearAttachments"));
+ CmdResolveImage = reinterpret_cast<PFN_vkCmdResolveImage>(GetDeviceProcAddr(dev, "vkCmdResolveImage"));
+ CmdSetEvent = reinterpret_cast<PFN_vkCmdSetEvent>(GetDeviceProcAddr(dev, "vkCmdSetEvent"));
+ CmdResetEvent = reinterpret_cast<PFN_vkCmdResetEvent>(GetDeviceProcAddr(dev, "vkCmdResetEvent"));
+ CmdWaitEvents = reinterpret_cast<PFN_vkCmdWaitEvents>(GetDeviceProcAddr(dev, "vkCmdWaitEvents"));
+ CmdPipelineBarrier = reinterpret_cast<PFN_vkCmdPipelineBarrier>(GetDeviceProcAddr(dev, "vkCmdPipelineBarrier"));
+ CmdBeginQuery = reinterpret_cast<PFN_vkCmdBeginQuery>(GetDeviceProcAddr(dev, "vkCmdBeginQuery"));
+ CmdEndQuery = reinterpret_cast<PFN_vkCmdEndQuery>(GetDeviceProcAddr(dev, "vkCmdEndQuery"));
+ CmdResetQueryPool = reinterpret_cast<PFN_vkCmdResetQueryPool>(GetDeviceProcAddr(dev, "vkCmdResetQueryPool"));
+ CmdWriteTimestamp = reinterpret_cast<PFN_vkCmdWriteTimestamp>(GetDeviceProcAddr(dev, "vkCmdWriteTimestamp"));
+ CmdCopyQueryPoolResults = reinterpret_cast<PFN_vkCmdCopyQueryPoolResults>(GetDeviceProcAddr(dev, "vkCmdCopyQueryPoolResults"));
+ CmdPushConstants = reinterpret_cast<PFN_vkCmdPushConstants>(GetDeviceProcAddr(dev, "vkCmdPushConstants"));
+ CmdBeginRenderPass = reinterpret_cast<PFN_vkCmdBeginRenderPass>(GetDeviceProcAddr(dev, "vkCmdBeginRenderPass"));
+ CmdNextSubpass = reinterpret_cast<PFN_vkCmdNextSubpass>(GetDeviceProcAddr(dev, "vkCmdNextSubpass"));
+ CmdEndRenderPass = reinterpret_cast<PFN_vkCmdEndRenderPass>(GetDeviceProcAddr(dev, "vkCmdEndRenderPass"));
+ CmdExecuteCommands = reinterpret_cast<PFN_vkCmdExecuteCommands>(GetDeviceProcAddr(dev, "vkCmdExecuteCommands"));
+ CreateSwapchainKHR = reinterpret_cast<PFN_vkCreateSwapchainKHR>(GetDeviceProcAddr(dev, "vkCreateSwapchainKHR"));
+ DestroySwapchainKHR = reinterpret_cast<PFN_vkDestroySwapchainKHR>(GetDeviceProcAddr(dev, "vkDestroySwapchainKHR"));
+ GetSwapchainImagesKHR = reinterpret_cast<PFN_vkGetSwapchainImagesKHR>(GetDeviceProcAddr(dev, "vkGetSwapchainImagesKHR"));
+ AcquireNextImageKHR = reinterpret_cast<PFN_vkAcquireNextImageKHR>(GetDeviceProcAddr(dev, "vkAcquireNextImageKHR"));
+ QueuePresentKHR = reinterpret_cast<PFN_vkQueuePresentKHR>(GetDeviceProcAddr(dev, "vkQueuePresentKHR"));
+ CreateSharedSwapchainsKHR = reinterpret_cast<PFN_vkCreateSharedSwapchainsKHR>(GetDeviceProcAddr(dev, "vkCreateSharedSwapchainsKHR"));
+}
+
+} // namespace vk
diff --git a/demos/smoke/HelpersDispatchTable.h b/demos/smoke/HelpersDispatchTable.h
new file mode 100644
index 00000000..19df7fbe
--- /dev/null
+++ b/demos/smoke/HelpersDispatchTable.h
@@ -0,0 +1,220 @@
+// This file is generated.
+#ifndef HELPERSDISPATCHTABLE_H
+#define HELPERSDISPATCHTABLE_H
+
+#include <vulkan/vulkan.h>
+
+namespace vk {
+
+// VK_core
+extern PFN_vkCreateInstance CreateInstance;
+extern PFN_vkDestroyInstance DestroyInstance;
+extern PFN_vkEnumeratePhysicalDevices EnumeratePhysicalDevices;
+extern PFN_vkGetPhysicalDeviceFeatures GetPhysicalDeviceFeatures;
+extern PFN_vkGetPhysicalDeviceFormatProperties GetPhysicalDeviceFormatProperties;
+extern PFN_vkGetPhysicalDeviceImageFormatProperties GetPhysicalDeviceImageFormatProperties;
+extern PFN_vkGetPhysicalDeviceProperties GetPhysicalDeviceProperties;
+extern PFN_vkGetPhysicalDeviceQueueFamilyProperties GetPhysicalDeviceQueueFamilyProperties;
+extern PFN_vkGetPhysicalDeviceMemoryProperties GetPhysicalDeviceMemoryProperties;
+extern PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
+extern PFN_vkGetDeviceProcAddr GetDeviceProcAddr;
+extern PFN_vkCreateDevice CreateDevice;
+extern PFN_vkDestroyDevice DestroyDevice;
+extern PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties;
+extern PFN_vkEnumerateDeviceExtensionProperties EnumerateDeviceExtensionProperties;
+extern PFN_vkEnumerateInstanceLayerProperties EnumerateInstanceLayerProperties;
+extern PFN_vkEnumerateDeviceLayerProperties EnumerateDeviceLayerProperties;
+extern PFN_vkGetDeviceQueue GetDeviceQueue;
+extern PFN_vkQueueSubmit QueueSubmit;
+extern PFN_vkQueueWaitIdle QueueWaitIdle;
+extern PFN_vkDeviceWaitIdle DeviceWaitIdle;
+extern PFN_vkAllocateMemory AllocateMemory;
+extern PFN_vkFreeMemory FreeMemory;
+extern PFN_vkMapMemory MapMemory;
+extern PFN_vkUnmapMemory UnmapMemory;
+extern PFN_vkFlushMappedMemoryRanges FlushMappedMemoryRanges;
+extern PFN_vkInvalidateMappedMemoryRanges InvalidateMappedMemoryRanges;
+extern PFN_vkGetDeviceMemoryCommitment GetDeviceMemoryCommitment;
+extern PFN_vkBindBufferMemory BindBufferMemory;
+extern PFN_vkBindImageMemory BindImageMemory;
+extern PFN_vkGetBufferMemoryRequirements GetBufferMemoryRequirements;
+extern PFN_vkGetImageMemoryRequirements GetImageMemoryRequirements;
+extern PFN_vkGetImageSparseMemoryRequirements GetImageSparseMemoryRequirements;
+extern PFN_vkGetPhysicalDeviceSparseImageFormatProperties GetPhysicalDeviceSparseImageFormatProperties;
+extern PFN_vkQueueBindSparse QueueBindSparse;
+extern PFN_vkCreateFence CreateFence;
+extern PFN_vkDestroyFence DestroyFence;
+extern PFN_vkResetFences ResetFences;
+extern PFN_vkGetFenceStatus GetFenceStatus;
+extern PFN_vkWaitForFences WaitForFences;
+extern PFN_vkCreateSemaphore CreateSemaphore;
+extern PFN_vkDestroySemaphore DestroySemaphore;
+extern PFN_vkCreateEvent CreateEvent;
+extern PFN_vkDestroyEvent DestroyEvent;
+extern PFN_vkGetEventStatus GetEventStatus;
+extern PFN_vkSetEvent SetEvent;
+extern PFN_vkResetEvent ResetEvent;
+extern PFN_vkCreateQueryPool CreateQueryPool;
+extern PFN_vkDestroyQueryPool DestroyQueryPool;
+extern PFN_vkGetQueryPoolResults GetQueryPoolResults;
+extern PFN_vkCreateBuffer CreateBuffer;
+extern PFN_vkDestroyBuffer DestroyBuffer;
+extern PFN_vkCreateBufferView CreateBufferView;
+extern PFN_vkDestroyBufferView DestroyBufferView;
+extern PFN_vkCreateImage CreateImage;
+extern PFN_vkDestroyImage DestroyImage;
+extern PFN_vkGetImageSubresourceLayout GetImageSubresourceLayout;
+extern PFN_vkCreateImageView CreateImageView;
+extern PFN_vkDestroyImageView DestroyImageView;
+extern PFN_vkCreateShaderModule CreateShaderModule;
+extern PFN_vkDestroyShaderModule DestroyShaderModule;
+extern PFN_vkCreatePipelineCache CreatePipelineCache;
+extern PFN_vkDestroyPipelineCache DestroyPipelineCache;
+extern PFN_vkGetPipelineCacheData GetPipelineCacheData;
+extern PFN_vkMergePipelineCaches MergePipelineCaches;
+extern PFN_vkCreateGraphicsPipelines CreateGraphicsPipelines;
+extern PFN_vkCreateComputePipelines CreateComputePipelines;
+extern PFN_vkDestroyPipeline DestroyPipeline;
+extern PFN_vkCreatePipelineLayout CreatePipelineLayout;
+extern PFN_vkDestroyPipelineLayout DestroyPipelineLayout;
+extern PFN_vkCreateSampler CreateSampler;
+extern PFN_vkDestroySampler DestroySampler;
+extern PFN_vkCreateDescriptorSetLayout CreateDescriptorSetLayout;
+extern PFN_vkDestroyDescriptorSetLayout DestroyDescriptorSetLayout;
+extern PFN_vkCreateDescriptorPool CreateDescriptorPool;
+extern PFN_vkDestroyDescriptorPool DestroyDescriptorPool;
+extern PFN_vkResetDescriptorPool ResetDescriptorPool;
+extern PFN_vkAllocateDescriptorSets AllocateDescriptorSets;
+extern PFN_vkFreeDescriptorSets FreeDescriptorSets;
+extern PFN_vkUpdateDescriptorSets UpdateDescriptorSets;
+extern PFN_vkCreateFramebuffer CreateFramebuffer;
+extern PFN_vkDestroyFramebuffer DestroyFramebuffer;
+extern PFN_vkCreateRenderPass CreateRenderPass;
+extern PFN_vkDestroyRenderPass DestroyRenderPass;
+extern PFN_vkGetRenderAreaGranularity GetRenderAreaGranularity;
+extern PFN_vkCreateCommandPool CreateCommandPool;
+extern PFN_vkDestroyCommandPool DestroyCommandPool;
+extern PFN_vkResetCommandPool ResetCommandPool;
+extern PFN_vkAllocateCommandBuffers AllocateCommandBuffers;
+extern PFN_vkFreeCommandBuffers FreeCommandBuffers;
+extern PFN_vkBeginCommandBuffer BeginCommandBuffer;
+extern PFN_vkEndCommandBuffer EndCommandBuffer;
+extern PFN_vkResetCommandBuffer ResetCommandBuffer;
+extern PFN_vkCmdBindPipeline CmdBindPipeline;
+extern PFN_vkCmdSetViewport CmdSetViewport;
+extern PFN_vkCmdSetScissor CmdSetScissor;
+extern PFN_vkCmdSetLineWidth CmdSetLineWidth;
+extern PFN_vkCmdSetDepthBias CmdSetDepthBias;
+extern PFN_vkCmdSetBlendConstants CmdSetBlendConstants;
+extern PFN_vkCmdSetDepthBounds CmdSetDepthBounds;
+extern PFN_vkCmdSetStencilCompareMask CmdSetStencilCompareMask;
+extern PFN_vkCmdSetStencilWriteMask CmdSetStencilWriteMask;
+extern PFN_vkCmdSetStencilReference CmdSetStencilReference;
+extern PFN_vkCmdBindDescriptorSets CmdBindDescriptorSets;
+extern PFN_vkCmdBindIndexBuffer CmdBindIndexBuffer;
+extern PFN_vkCmdBindVertexBuffers CmdBindVertexBuffers;
+extern PFN_vkCmdDraw CmdDraw;
+extern PFN_vkCmdDrawIndexed CmdDrawIndexed;
+extern PFN_vkCmdDrawIndirect CmdDrawIndirect;
+extern PFN_vkCmdDrawIndexedIndirect CmdDrawIndexedIndirect;
+extern PFN_vkCmdDispatch CmdDispatch;
+extern PFN_vkCmdDispatchIndirect CmdDispatchIndirect;
+extern PFN_vkCmdCopyBuffer CmdCopyBuffer;
+extern PFN_vkCmdCopyImage CmdCopyImage;
+extern PFN_vkCmdBlitImage CmdBlitImage;
+extern PFN_vkCmdCopyBufferToImage CmdCopyBufferToImage;
+extern PFN_vkCmdCopyImageToBuffer CmdCopyImageToBuffer;
+extern PFN_vkCmdUpdateBuffer CmdUpdateBuffer;
+extern PFN_vkCmdFillBuffer CmdFillBuffer;
+extern PFN_vkCmdClearColorImage CmdClearColorImage;
+extern PFN_vkCmdClearDepthStencilImage CmdClearDepthStencilImage;
+extern PFN_vkCmdClearAttachments CmdClearAttachments;
+extern PFN_vkCmdResolveImage CmdResolveImage;
+extern PFN_vkCmdSetEvent CmdSetEvent;
+extern PFN_vkCmdResetEvent CmdResetEvent;
+extern PFN_vkCmdWaitEvents CmdWaitEvents;
+extern PFN_vkCmdPipelineBarrier CmdPipelineBarrier;
+extern PFN_vkCmdBeginQuery CmdBeginQuery;
+extern PFN_vkCmdEndQuery CmdEndQuery;
+extern PFN_vkCmdResetQueryPool CmdResetQueryPool;
+extern PFN_vkCmdWriteTimestamp CmdWriteTimestamp;
+extern PFN_vkCmdCopyQueryPoolResults CmdCopyQueryPoolResults;
+extern PFN_vkCmdPushConstants CmdPushConstants;
+extern PFN_vkCmdBeginRenderPass CmdBeginRenderPass;
+extern PFN_vkCmdNextSubpass CmdNextSubpass;
+extern PFN_vkCmdEndRenderPass CmdEndRenderPass;
+extern PFN_vkCmdExecuteCommands CmdExecuteCommands;
+
+// VK_KHR_surface
+extern PFN_vkDestroySurfaceKHR DestroySurfaceKHR;
+extern PFN_vkGetPhysicalDeviceSurfaceSupportKHR GetPhysicalDeviceSurfaceSupportKHR;
+extern PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR GetPhysicalDeviceSurfaceCapabilitiesKHR;
+extern PFN_vkGetPhysicalDeviceSurfaceFormatsKHR GetPhysicalDeviceSurfaceFormatsKHR;
+extern PFN_vkGetPhysicalDeviceSurfacePresentModesKHR GetPhysicalDeviceSurfacePresentModesKHR;
+
+// VK_KHR_swapchain
+extern PFN_vkCreateSwapchainKHR CreateSwapchainKHR;
+extern PFN_vkDestroySwapchainKHR DestroySwapchainKHR;
+extern PFN_vkGetSwapchainImagesKHR GetSwapchainImagesKHR;
+extern PFN_vkAcquireNextImageKHR AcquireNextImageKHR;
+extern PFN_vkQueuePresentKHR QueuePresentKHR;
+
+// VK_KHR_display
+extern PFN_vkGetPhysicalDeviceDisplayPropertiesKHR GetPhysicalDeviceDisplayPropertiesKHR;
+extern PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR GetPhysicalDeviceDisplayPlanePropertiesKHR;
+extern PFN_vkGetDisplayPlaneSupportedDisplaysKHR GetDisplayPlaneSupportedDisplaysKHR;
+extern PFN_vkGetDisplayModePropertiesKHR GetDisplayModePropertiesKHR;
+extern PFN_vkCreateDisplayModeKHR CreateDisplayModeKHR;
+extern PFN_vkGetDisplayPlaneCapabilitiesKHR GetDisplayPlaneCapabilitiesKHR;
+extern PFN_vkCreateDisplayPlaneSurfaceKHR CreateDisplayPlaneSurfaceKHR;
+
+// VK_KHR_display_swapchain
+extern PFN_vkCreateSharedSwapchainsKHR CreateSharedSwapchainsKHR;
+
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+// VK_KHR_xlib_surface
+extern PFN_vkCreateXlibSurfaceKHR CreateXlibSurfaceKHR;
+extern PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR GetPhysicalDeviceXlibPresentationSupportKHR;
+#endif
+
+#ifdef VK_USE_PLATFORM_XCB_KHR
+// VK_KHR_xcb_surface
+extern PFN_vkCreateXcbSurfaceKHR CreateXcbSurfaceKHR;
+extern PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR GetPhysicalDeviceXcbPresentationSupportKHR;
+#endif
+
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+// VK_KHR_wayland_surface
+extern PFN_vkCreateWaylandSurfaceKHR CreateWaylandSurfaceKHR;
+extern PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR GetPhysicalDeviceWaylandPresentationSupportKHR;
+#endif
+
+#ifdef VK_USE_PLATFORM_MIR_KHR
+// VK_KHR_mir_surface
+extern PFN_vkCreateMirSurfaceKHR CreateMirSurfaceKHR;
+extern PFN_vkGetPhysicalDeviceMirPresentationSupportKHR GetPhysicalDeviceMirPresentationSupportKHR;
+#endif
+
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+// VK_KHR_android_surface
+extern PFN_vkCreateAndroidSurfaceKHR CreateAndroidSurfaceKHR;
+#endif
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+// VK_KHR_win32_surface
+extern PFN_vkCreateWin32SurfaceKHR CreateWin32SurfaceKHR;
+extern PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR GetPhysicalDeviceWin32PresentationSupportKHR;
+#endif
+
+// VK_EXT_debug_report
+extern PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallbackEXT;
+extern PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallbackEXT;
+extern PFN_vkDebugReportMessageEXT DebugReportMessageEXT;
+
+void init_dispatch_table_top(PFN_vkGetInstanceProcAddr get_instance_proc_addr);
+void init_dispatch_table_middle(VkInstance instance, bool include_bottom);
+void init_dispatch_table_bottom(VkInstance instance, VkDevice dev);
+
+} // namespace vk
+
+#endif // HELPERSDISPATCHTABLE_H
diff --git a/demos/smoke/Main.cpp b/demos/smoke/Main.cpp
new file mode 100644
index 00000000..4f24b74b
--- /dev/null
+++ b/demos/smoke/Main.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2016 Google, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <string>
+#include <vector>
+
+#include "Smoke.h"
+
+namespace {
+
+Game *create_game(int argc, char **argv)
+{
+ std::vector<std::string> args(argv, argv + argc);
+ return new Smoke(args);
+}
+
+} // namespace
+
+#if defined(VK_USE_PLATFORM_XCB_KHR)
+
+#include "ShellXcb.h"
+
+int main(int argc, char **argv)
+{
+ Game *game = create_game(argc, argv);
+ {
+ ShellXcb shell(*game);
+ shell.run();
+ }
+ delete game;
+
+ return 0;
+}
+
+#elif defined(VK_USE_PLATFORM_ANDROID_KHR)
+
+#include <android/log.h>
+#include "ShellAndroid.h"
+
+void android_main(android_app *app)
+{
+ Game *game = create_game(0, nullptr);
+
+ try {
+ ShellAndroid shell(*app, *game);
+ shell.run();
+ } catch (const std::runtime_error &e) {
+ __android_log_print(ANDROID_LOG_ERROR, game->settings().name.c_str(),
+ "%s", e.what());
+ }
+
+ delete game;
+}
+
+#elif defined(VK_USE_PLATFORM_WIN32_KHR)
+
+#include "ShellWin32.h"
+
+int main(int argc, char **argv)
+{
+ Game *game = create_game(argc, argv);
+ {
+ ShellWin32 shell(*game);
+ shell.run();
+ }
+ delete game;
+
+ return 0;
+}
+
+#endif // VK_USE_PLATFORM_XCB_KHR
diff --git a/demos/smoke/Meshes.cpp b/demos/smoke/Meshes.cpp
new file mode 100644
index 00000000..5fdb8fad
--- /dev/null
+++ b/demos/smoke/Meshes.cpp
@@ -0,0 +1,537 @@
+/*
+ * Copyright (C) 2016 Google, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <cassert>
+#include <cmath>
+#include <cstring>
+#include <array>
+#include <unordered_map>
+
+#include "Helpers.h"
+#include "Meshes.h"
+
+namespace {
+
+class Mesh {
+public:
+ struct Position {
+ float x;
+ float y;
+ float z;
+ };
+
+ struct Normal {
+ float x;
+ float y;
+ float z;
+ };
+
+ struct Face {
+ int v0;
+ int v1;
+ int v2;
+ };
+
+ static uint32_t vertex_stride()
+ {
+ // Position + Normal
+ const int comp_count = 6;
+
+ return sizeof(float) * comp_count;
+ }
+
+ static VkVertexInputBindingDescription vertex_input_binding()
+ {
+ VkVertexInputBindingDescription vi_binding = {};
+ vi_binding.binding = 0;
+ vi_binding.stride = vertex_stride();
+ vi_binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
+
+ return vi_binding;
+ }
+
+ static std::vector<VkVertexInputAttributeDescription> vertex_input_attributes()
+ {
+ std::vector<VkVertexInputAttributeDescription> vi_attrs(2);
+ // Position
+ vi_attrs[0].location = 0;
+ vi_attrs[0].binding = 0;
+ vi_attrs[0].format = VK_FORMAT_R32G32B32_SFLOAT;
+ vi_attrs[0].offset = 0;
+ // Normal
+ vi_attrs[1].location = 1;
+ vi_attrs[1].binding = 0;
+ vi_attrs[1].format = VK_FORMAT_R32G32B32_SFLOAT;
+ vi_attrs[1].offset = sizeof(float) * 3;
+
+ return vi_attrs;
+ }
+
+ static VkIndexType index_type()
+ {
+ return VK_INDEX_TYPE_UINT32;
+ }
+
+ static VkPipelineInputAssemblyStateCreateInfo input_assembly_state()
+ {
+ VkPipelineInputAssemblyStateCreateInfo ia_info = {};
+ ia_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
+ ia_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ ia_info.primitiveRestartEnable = false;
+ return ia_info;
+ }
+
+ void build(const std::vector<std::array<float, 6>> &vertices, const std::vector<std::array<int, 3>> &faces)
+ {
+ positions_.reserve(vertices.size());
+ normals_.reserve(vertices.size());
+ for (const auto &v : vertices) {
+ positions_.emplace_back(Position{ v[0], v[1], v[2] });
+ normals_.emplace_back(Normal{ v[3], v[4], v[5] });
+ }
+
+ faces_.reserve(faces.size());
+ for (const auto &f : faces)
+ faces_.emplace_back(Face{ f[0], f[1], f[2] });
+ }
+
+ uint32_t vertex_count() const
+ {
+ return positions_.size();
+ }
+
+ VkDeviceSize vertex_buffer_size() const
+ {
+ return vertex_stride() * vertex_count();
+ }
+
+ void vertex_buffer_write(void *data) const
+ {
+ float *dst = reinterpret_cast<float *>(data);
+ for (size_t i = 0; i < positions_.size(); i++) {
+ const Position &pos = positions_[i];
+ const Normal &normal = normals_[i];
+ dst[0] = pos.x;
+ dst[1] = pos.y;
+ dst[2] = pos.z;
+ dst[3] = normal.x;
+ dst[4] = normal.y;
+ dst[5] = normal.z;
+ dst += 6;
+ }
+ }
+
+ uint32_t index_count() const
+ {
+ return faces_.size() * 3;
+ }
+
+ VkDeviceSize index_buffer_size() const
+ {
+ return sizeof(uint32_t) * index_count();
+ }
+
+ void index_buffer_write(void *data) const
+ {
+ uint32_t *dst = reinterpret_cast<uint32_t *>(data);
+ for (const auto &face : faces_) {
+ dst[0] = face.v0;
+ dst[1] = face.v1;
+ dst[2] = face.v2;
+ dst += 3;
+ }
+ }
+
+ std::vector<Position> positions_;
+ std::vector<Normal> normals_;
+ std::vector<Face> faces_;
+};
+
+class BuildPyramid {
+public:
+ BuildPyramid(Mesh &mesh)
+ {
+ const std::vector<std::array<float, 6>> vertices = {
+ // position normal
+ { 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f },
+ { -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f },
+ { 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f },
+ { 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f },
+ { -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f },
+ };
+
+ const std::vector<std::array<int, 3>> faces = {
+ { 0, 1, 2 },
+ { 0, 2, 3 },
+ { 0, 3, 4 },
+ { 0, 4, 1 },
+ { 1, 4, 3 },
+ { 1, 3, 2 },
+ };
+
+ mesh.build(vertices, faces);
+ }
+};
+
+class BuildIcosphere {
+public:
+ BuildIcosphere(Mesh &mesh) : mesh_(mesh), radius_(1.0f)
+ {
+ const int tessellate_level = 2;
+
+ build_icosahedron();
+ for (int i = 0; i < tessellate_level; i++)
+ tessellate();
+ }
+
+private:
+ void build_icosahedron()
+ {
+ // https://en.wikipedia.org/wiki/Regular_icosahedron
+ const float l1 = std::sqrt(2.0f / (5.0f + std::sqrt(5.0f))) * radius_;
+ const float l2 = std::sqrt(2.0f / (5.0f - std::sqrt(5.0f))) * radius_;
+ // vertices are from three golden rectangles
+ const std::vector<std::array<float, 6>> icosahedron_vertices = {
+ // position normal
+ { -l1, -l2, 0.0f, -l1, -l2, 0.0f, },
+ { l1, -l2, 0.0f, l1, -l2, 0.0f, },
+ { l1, l2, 0.0f, l1, l2, 0.0f, },
+ { -l1, l2, 0.0f, -l1, l2, 0.0f, },
+
+ { -l2, 0.0f, -l1, -l2, 0.0f, -l1, },
+ { l2, 0.0f, -l1, l2, 0.0f, -l1, },
+ { l2, 0.0f, l1, l2, 0.0f, l1, },
+ { -l2, 0.0f, l1, -l2, 0.0f, l1, },
+
+ { 0.0f, -l1, -l2, 0.0f, -l1, -l2, },
+ { 0.0f, l1, -l2, 0.0f, l1, -l2, },
+ { 0.0f, l1, l2, 0.0f, l1, l2, },
+ { 0.0f, -l1, l2, 0.0f, -l1, l2, },
+ };
+ const std::vector<std::array<int, 3>> icosahedron_faces = {
+ // triangles sharing vertex 0
+ { 0, 1, 11 },
+ { 0, 11, 7 },
+ { 0, 7, 4 },
+ { 0, 4, 8 },
+ { 0, 8, 1 },
+ // adjacent triangles
+ { 11, 1, 6 },
+ { 7, 11, 10 },
+ { 4, 7, 3 },
+ { 8, 4, 9 },
+ { 1, 8, 5 },
+ // triangles sharing vertex 2
+ { 2, 3, 10 },
+ { 2, 10, 6 },
+ { 2, 6, 5 },
+ { 2, 5, 9 },
+ { 2, 9, 3 },
+ // adjacent triangles
+ { 10, 3, 7 },
+ { 6, 10, 11 },
+ { 5, 6, 1 },
+ { 9, 5, 8 },
+ { 3, 9, 4 },
+ };
+
+ mesh_.build(icosahedron_vertices, icosahedron_faces);
+ }
+
+ void tessellate()
+ {
+ size_t middle_point_count = mesh_.faces_.size() * 3 / 2;
+ size_t final_face_count = mesh_.faces_.size() * 4;
+
+ std::vector<Mesh::Face> faces;
+ faces.reserve(final_face_count);
+
+ middle_points_.clear();
+ middle_points_.reserve(middle_point_count);
+
+ mesh_.positions_.reserve(mesh_.vertex_count() + middle_point_count);
+ mesh_.normals_.reserve(mesh_.vertex_count() + middle_point_count);
+
+ for (const auto &f : mesh_.faces_) {
+ int v0 = f.v0;
+ int v1 = f.v1;
+ int v2 = f.v2;
+
+ int v01 = add_middle_point(v0, v1);
+ int v12 = add_middle_point(v1, v2);
+ int v20 = add_middle_point(v2, v0);
+
+ faces.emplace_back(Mesh::Face{ v0, v01, v20 });
+ faces.emplace_back(Mesh::Face{ v1, v12, v01 });
+ faces.emplace_back(Mesh::Face{ v2, v20, v12 });
+ faces.emplace_back(Mesh::Face{ v01, v12, v20 });
+ }
+
+ mesh_.faces_.swap(faces);
+ }
+
+ int add_middle_point(int a, int b)
+ {
+ uint64_t key = (a < b) ? ((uint64_t) a << 32 | b) : ((uint64_t) b << 32 | a);
+ auto it = middle_points_.find(key);
+ if (it != middle_points_.end())
+ return it->second;
+
+ const Mesh::Position &pos_a = mesh_.positions_[a];
+ const Mesh::Position &pos_b = mesh_.positions_[b];
+ Mesh::Position pos_mid = {
+ (pos_a.x + pos_b.x) / 2.0f,
+ (pos_a.y + pos_b.y) / 2.0f,
+ (pos_a.z + pos_b.z) / 2.0f,
+ };
+ float scale = radius_ / std::sqrt(pos_mid.x * pos_mid.x +
+ pos_mid.y * pos_mid.y +
+ pos_mid.z * pos_mid.z);
+ pos_mid.x *= scale;
+ pos_mid.y *= scale;
+ pos_mid.z *= scale;
+
+ Mesh::Normal normal_mid = { pos_mid.x, pos_mid.y, pos_mid.z };
+ normal_mid.x /= radius_;
+ normal_mid.y /= radius_;
+ normal_mid.z /= radius_;
+
+ mesh_.positions_.emplace_back(pos_mid);
+ mesh_.normals_.emplace_back(normal_mid);
+
+ int mid = mesh_.vertex_count() - 1;
+ middle_points_.emplace(std::make_pair(key, mid));
+
+ return mid;
+ }
+
+ Mesh &mesh_;
+ const float radius_;
+ std::unordered_map<uint64_t, uint32_t> middle_points_;
+};
+
+class BuildTeapot {
+public:
+ BuildTeapot(Mesh &mesh)
+ {
+#include "Meshes.teapot.h"
+ const int position_count = sizeof(teapot_positions) / sizeof(teapot_positions[0]);
+ const int index_count = sizeof(teapot_indices) / sizeof(teapot_indices[0]);
+ assert(position_count % 3 == 0 && index_count % 3 == 0);
+
+ Mesh::Position translate;
+ float scale;
+ get_transform(teapot_positions, position_count, translate, scale);
+
+ for (int i = 0; i < position_count; i += 3) {
+ mesh.positions_.emplace_back(Mesh::Position{
+ (teapot_positions[i + 0] + translate.x) * scale,
+ (teapot_positions[i + 1] + translate.y) * scale,
+ (teapot_positions[i + 2] + translate.z) * scale,
+ });
+
+ mesh.normals_.emplace_back(Mesh::Normal{
+ teapot_normals[i + 0],
+ teapot_normals[i + 1],
+ teapot_normals[i + 2],
+ });
+ }
+
+ for (int i = 0; i < index_count; i += 3) {
+ mesh.faces_.emplace_back(Mesh::Face{
+ teapot_indices[i + 0],
+ teapot_indices[i + 1],
+ teapot_indices[i + 2]
+ });
+ }
+ }
+
+ void get_transform(const float *positions, int position_count,
+ Mesh::Position &translate, float &scale)
+ {
+ float min[3] = {
+ positions[0],
+ positions[1],
+ positions[2],
+ };
+ float max[3] = {
+ positions[0],
+ positions[1],
+ positions[2],
+ };
+ for (int i = 3; i < position_count; i += 3) {
+ for (int j = 0; j < 3; j++) {
+ if (min[j] > positions[i + j])
+ min[j] = positions[i + j];
+ if (max[j] < positions[i + j])
+ max[j] = positions[i + j];
+ }
+ }
+
+ translate.x = -(min[0] + max[0]) / 2.0f;
+ translate.y = -(min[1] + max[1]) / 2.0f;
+ translate.z = -(min[2] + max[2]) / 2.0f;
+
+ float extents[3] = {
+ max[0] + translate.x,
+ max[1] + translate.y,
+ max[2] + translate.z,
+ };
+
+ float max_extent = extents[0];
+ if (max_extent < extents[1])
+ max_extent = extents[1];
+ if (max_extent < extents[2])
+ max_extent = extents[2];
+
+ scale = 1.0f / max_extent;
+ }
+};
+
+void build_meshes(std::array<Mesh, Meshes::MESH_COUNT> &meshes)
+{
+ BuildPyramid build_pyramid(meshes[Meshes::MESH_PYRAMID]);
+ BuildIcosphere build_icosphere(meshes[Meshes::MESH_ICOSPHERE]);
+ BuildTeapot build_teapot(meshes[Meshes::MESH_TEAPOT]);
+}
+
+} // namespace
+
+Meshes::Meshes(VkDevice dev, const std::vector<VkMemoryPropertyFlags> &mem_flags)
+ : dev_(dev),
+ vertex_input_binding_(Mesh::vertex_input_binding()),
+ vertex_input_attrs_(Mesh::vertex_input_attributes()),
+ vertex_input_state_(),
+ input_assembly_state_(Mesh::input_assembly_state()),
+ index_type_(Mesh::index_type())
+{
+ vertex_input_state_.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
+ vertex_input_state_.vertexBindingDescriptionCount = 1;
+ vertex_input_state_.pVertexBindingDescriptions = &vertex_input_binding_;
+ vertex_input_state_.vertexAttributeDescriptionCount = static_cast<uint32_t>(vertex_input_attrs_.size());
+ vertex_input_state_.pVertexAttributeDescriptions = vertex_input_attrs_.data();
+
+ std::array<Mesh, MESH_COUNT> meshes;
+ build_meshes(meshes);
+
+ draw_commands_.reserve(meshes.size());
+ uint32_t first_index = 0;
+ int32_t vertex_offset = 0;
+ VkDeviceSize vb_size = 0;
+ VkDeviceSize ib_size = 0;
+ for (const auto &mesh : meshes) {
+ VkDrawIndexedIndirectCommand draw = {};
+ draw.indexCount = mesh.index_count();
+ draw.instanceCount = 1;
+ draw.firstIndex = first_index;
+ draw.vertexOffset = vertex_offset;
+ draw.firstInstance = 0;
+
+ draw_commands_.push_back(draw);
+
+ first_index += mesh.index_count();
+ vertex_offset += mesh.vertex_count();
+ vb_size += mesh.vertex_buffer_size();
+ ib_size += mesh.index_buffer_size();
+ }
+
+ allocate_resources(vb_size, ib_size, mem_flags);
+
+ uint8_t *vb_data, *ib_data;
+ vk::assert_success(vk::MapMemory(dev_, mem_, 0, VK_WHOLE_SIZE,
+ 0, reinterpret_cast<void **>(&vb_data)));
+ ib_data = vb_data + ib_mem_offset_;
+
+ for (const auto &mesh : meshes) {
+ mesh.vertex_buffer_write(vb_data);
+ mesh.index_buffer_write(ib_data);
+ vb_data += mesh.vertex_buffer_size();
+ ib_data += mesh.index_buffer_size();
+ }
+
+ vk::UnmapMemory(dev_, mem_);
+}
+
+Meshes::~Meshes()
+{
+ vk::FreeMemory(dev_, mem_, nullptr);
+ vk::DestroyBuffer(dev_, vb_, nullptr);
+ vk::DestroyBuffer(dev_, ib_, nullptr);
+}
+
+void Meshes::cmd_bind_buffers(VkCommandBuffer cmd) const
+{
+ const VkDeviceSize vb_offset = 0;
+ vk::CmdBindVertexBuffers(cmd, 0, 1, &vb_, &vb_offset);
+
+ vk::CmdBindIndexBuffer(cmd, ib_, 0, index_type_);
+}
+
+void Meshes::cmd_draw(VkCommandBuffer cmd, Type type) const
+{
+ const auto &draw = draw_commands_[type];
+ vk::CmdDrawIndexed(cmd, draw.indexCount, draw.instanceCount,
+ draw.firstIndex, draw.vertexOffset, draw.firstInstance);
+}
+
+void Meshes::allocate_resources(VkDeviceSize vb_size, VkDeviceSize ib_size, const std::vector<VkMemoryPropertyFlags> &mem_flags)
+{
+ VkBufferCreateInfo buf_info = {};
+ buf_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+ buf_info.size = vb_size;
+ buf_info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
+ buf_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ vk::CreateBuffer(dev_, &buf_info, nullptr, &vb_);
+
+ buf_info.size = ib_size;
+ buf_info.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
+ vk::CreateBuffer(dev_, &buf_info, nullptr, &ib_);
+
+ VkMemoryRequirements vb_mem_reqs, ib_mem_reqs;
+ vk::GetBufferMemoryRequirements(dev_, vb_, &vb_mem_reqs);
+ vk::GetBufferMemoryRequirements(dev_, ib_, &ib_mem_reqs);
+
+ // indices follow vertices
+ ib_mem_offset_ = vb_mem_reqs.size +
+ (ib_mem_reqs.alignment - (vb_mem_reqs.size % ib_mem_reqs.alignment));
+
+ VkMemoryAllocateInfo mem_info = {};
+ mem_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+ mem_info.allocationSize = ib_mem_offset_ + ib_mem_reqs.size;
+
+ // find any supported and mappable memory type
+ uint32_t mem_types = (vb_mem_reqs.memoryTypeBits & ib_mem_reqs.memoryTypeBits);
+ for (uint32_t idx = 0; idx < mem_flags.size(); idx++) {
+ if ((mem_types & (1 << idx)) &&
+ (mem_flags[idx] & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) &&
+ (mem_flags[idx] & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
+ // TODO this may not be reachable
+ mem_info.memoryTypeIndex = idx;
+ break;
+ }
+ }
+
+ vk::AllocateMemory(dev_, &mem_info, nullptr, &mem_);
+
+ vk::BindBufferMemory(dev_, vb_, mem_, 0);
+ vk::BindBufferMemory(dev_, ib_, mem_, ib_mem_offset_);
+}
diff --git a/demos/smoke/Meshes.h b/demos/smoke/Meshes.h
new file mode 100644
index 00000000..2fb9e3fe
--- /dev/null
+++ b/demos/smoke/Meshes.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2016 Google, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef MESHES_H
+#define MESHES_H
+
+#include <vulkan/vulkan.h>
+#include <vector>
+
+class Meshes {
+public:
+ Meshes(VkDevice dev, const std::vector<VkMemoryPropertyFlags> &mem_flags);
+ ~Meshes();
+
+ const VkPipelineVertexInputStateCreateInfo &vertex_input_state() const { return vertex_input_state_; }
+ const VkPipelineInputAssemblyStateCreateInfo &input_assembly_state() const { return input_assembly_state_; }
+
+ enum Type {
+ MESH_PYRAMID,
+ MESH_ICOSPHERE,
+ MESH_TEAPOT,
+
+ MESH_COUNT,
+ };
+
+ void cmd_bind_buffers(VkCommandBuffer cmd) const;
+ void cmd_draw(VkCommandBuffer cmd, Type type) const;
+
+private:
+ void allocate_resources(VkDeviceSize vb_size, VkDeviceSize ib_size, const std::vector<VkMemoryPropertyFlags> &mem_flags);
+
+ VkDevice dev_;
+
+ VkVertexInputBindingDescription vertex_input_binding_;
+ std::vector<VkVertexInputAttributeDescription> vertex_input_attrs_;
+ VkPipelineVertexInputStateCreateInfo vertex_input_state_;
+ VkPipelineInputAssemblyStateCreateInfo input_assembly_state_;
+ VkIndexType index_type_;
+
+ std::vector<VkDrawIndexedIndirectCommand> draw_commands_;
+
+ VkBuffer vb_;
+ VkBuffer ib_;
+ VkDeviceMemory mem_;
+ VkDeviceSize ib_mem_offset_;
+};
+
+#endif // MESHES_H
diff --git a/demos/smoke/Meshes.teapot.h b/demos/smoke/Meshes.teapot.h
new file mode 100644
index 00000000..68aa2974
--- /dev/null
+++ b/demos/smoke/Meshes.teapot.h
@@ -0,0 +1,2666 @@
+/*
+ * Copyright (c) 2009 The Chromium Authors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Modified from
+//
+// https://raw.githubusercontent.com/KhronosGroup/WebGL/master/sdk/demos/google/shiny-teapot/teapot-streams.js
+
+static const float teapot_positions[] = {
+ 17.83489990234375f, 0.0f, 30.573999404907227f,
+ 16.452699661254883f, -7.000179767608643f, 30.573999404907227f,
+ 16.223100662231445f, -6.902520179748535f, 31.51460075378418f,
+ 17.586000442504883f, 0.0f, 31.51460075378418f,
+ 16.48940086364746f, -7.015810012817383f, 31.828100204467773f,
+ 17.87470054626465f, 0.0f, 31.828100204467773f,
+ 17.031099319458008f, -7.246280193328857f, 31.51460075378418f,
+ 18.46190071105957f, 0.0f, 31.51460075378418f,
+ 17.62779998779297f, -7.500199794769287f, 30.573999404907227f,
+ 19.108800888061523f, 0.0f, 30.573999404907227f,
+ 12.662699699401855f, -12.662699699401855f, 30.573999404907227f,
+ 12.486100196838379f, -12.486100196838379f, 31.51460075378418f,
+ 12.690999984741211f, -12.690999984741211f, 31.828100204467773f,
+ 13.10789966583252f, -13.10789966583252f, 31.51460075378418f,
+ 13.56719970703125f, -13.56719970703125f, 30.573999404907227f,
+ 7.000179767608643f, -16.452699661254883f, 30.573999404907227f,
+ 6.902520179748535f, -16.223100662231445f, 31.51460075378418f,
+ 7.015810012817383f, -16.48940086364746f, 31.828100204467773f,
+ 7.246280193328857f, -17.031099319458008f, 31.51460075378418f,
+ 7.500199794769287f, -17.62779998779297f, 30.573999404907227f,
+ 0.0f, -17.83489990234375f, 30.573999404907227f,
+ 0.0f, -17.586000442504883f, 31.51460075378418f,
+ 0.0f, -17.87470054626465f, 31.828100204467773f,
+ 0.0f, -18.46190071105957f, 31.51460075378418f,
+ 0.0f, -19.108800888061523f, 30.573999404907227f,
+ 0.0f, -17.83489990234375f, 30.573999404907227f,
+ -7.483870029449463f, -16.452699661254883f, 30.573999404907227f,
+ -7.106579780578613f, -16.223100662231445f, 31.51460075378418f,
+ 0.0f, -17.586000442504883f, 31.51460075378418f,
+ -7.07627010345459f, -16.48940086364746f, 31.828100204467773f,
+ 0.0f, -17.87470054626465f, 31.828100204467773f,
+ -7.25383996963501f, -17.031099319458008f, 31.51460075378418f,
+ 0.0f, -18.46190071105957f, 31.51460075378418f,
+ -7.500199794769287f, -17.62779998779297f, 30.573999404907227f,
+ 0.0f, -19.108800888061523f, 30.573999404907227f,
+ -13.092700004577637f, -12.662699699401855f, 30.573999404907227f,
+ -12.667499542236328f, -12.486100196838379f, 31.51460075378418f,
+ -12.744799613952637f, -12.690999984741211f, 31.828100204467773f,
+ -13.11460018157959f, -13.10789966583252f, 31.51460075378418f,
+ -13.56719970703125f, -13.56719970703125f, 30.573999404907227f,
+ -16.61389923095703f, -7.000179767608643f, 30.573999404907227f,
+ -16.291099548339844f, -6.902520179748535f, 31.51460075378418f,
+ -16.50950050354004f, -7.015810012817383f, 31.828100204467773f,
+ -17.033599853515625f, -7.246280193328857f, 31.51460075378418f,
+ -17.62779998779297f, -7.500199794769287f, 30.573999404907227f,
+ -17.83489990234375f, 0.0f, 30.573999404907227f,
+ -17.586000442504883f, 0.0f, 31.51460075378418f,
+ -17.87470054626465f, 0.0f, 31.828100204467773f,
+ -18.46190071105957f, 0.0f, 31.51460075378418f,
+ -19.108800888061523f, 0.0f, 30.573999404907227f,
+ -17.83489990234375f, 0.0f, 30.573999404907227f,
+ -16.452699661254883f, 7.000179767608643f, 30.573999404907227f,
+ -16.223100662231445f, 6.902520179748535f, 31.51460075378418f,
+ -17.586000442504883f, 0.0f, 31.51460075378418f,
+ -16.48940086364746f, 7.015810012817383f, 31.828100204467773f,
+ -17.87470054626465f, 0.0f, 31.828100204467773f,
+ -17.031099319458008f, 7.246280193328857f, 31.51460075378418f,
+ -18.46190071105957f, 0.0f, 31.51460075378418f,
+ -17.62779998779297f, 7.500199794769287f, 30.573999404907227f,
+ -19.108800888061523f, 0.0f, 30.573999404907227f,
+ -12.662699699401855f, 12.662699699401855f, 30.573999404907227f,
+ -12.486100196838379f, 12.486100196838379f, 31.51460075378418f,
+ -12.690999984741211f, 12.690999984741211f, 31.828100204467773f,
+ -13.10789966583252f, 13.10789966583252f, 31.51460075378418f,
+ -13.56719970703125f, 13.56719970703125f, 30.573999404907227f,
+ -7.000179767608643f, 16.452699661254883f, 30.573999404907227f,
+ -6.902520179748535f, 16.223100662231445f, 31.51460075378418f,
+ -7.015810012817383f, 16.48940086364746f, 31.828100204467773f,
+ -7.246280193328857f, 17.031099319458008f, 31.51460075378418f,
+ -7.500199794769287f, 17.62779998779297f, 30.573999404907227f,
+ 0.0f, 17.83489990234375f, 30.573999404907227f,
+ 0.0f, 17.586000442504883f, 31.51460075378418f,
+ 0.0f, 17.87470054626465f, 31.828100204467773f,
+ 0.0f, 18.46190071105957f, 31.51460075378418f,
+ 0.0f, 19.108800888061523f, 30.573999404907227f,
+ 0.0f, 17.83489990234375f, 30.573999404907227f,
+ 7.000179767608643f, 16.452699661254883f, 30.573999404907227f,
+ 6.902520179748535f, 16.223100662231445f, 31.51460075378418f,
+ 0.0f, 17.586000442504883f, 31.51460075378418f,
+ 7.015810012817383f, 16.48940086364746f, 31.828100204467773f,
+ 0.0f, 17.87470054626465f, 31.828100204467773f,
+ 7.246280193328857f, 17.031099319458008f, 31.51460075378418f,
+ 0.0f, 18.46190071105957f, 31.51460075378418f,
+ 7.500199794769287f, 17.62779998779297f, 30.573999404907227f,
+ 0.0f, 19.108800888061523f, 30.573999404907227f,
+ 12.662699699401855f, 12.662699699401855f, 30.573999404907227f,
+ 12.486100196838379f, 12.486100196838379f, 31.51460075378418f,
+ 12.690999984741211f, 12.690999984741211f, 31.828100204467773f,
+ 13.10789966583252f, 13.10789966583252f, 31.51460075378418f,
+ 13.56719970703125f, 13.56719970703125f, 30.573999404907227f,
+ 16.452699661254883f, 7.000179767608643f, 30.573999404907227f,
+ 16.223100662231445f, 6.902520179748535f, 31.51460075378418f,
+ 16.48940086364746f, 7.015810012817383f, 31.828100204467773f,
+ 17.031099319458008f, 7.246280193328857f, 31.51460075378418f,
+ 17.62779998779297f, 7.500199794769287f, 30.573999404907227f,
+ 17.83489990234375f, 0.0f, 30.573999404907227f,
+ 17.586000442504883f, 0.0f, 31.51460075378418f,
+ 17.87470054626465f, 0.0f, 31.828100204467773f,
+ 18.46190071105957f, 0.0f, 31.51460075378418f,
+ 19.108800888061523f, 0.0f, 30.573999404907227f,
+ 19.108800888061523f, 0.0f, 30.573999404907227f,
+ 17.62779998779297f, -7.500199794769287f, 30.573999404907227f,
+ 19.785400390625f, -8.418190002441406f, 25.572900772094727f,
+ 21.447599411010742f, 0.0f, 25.572900772094727f,
+ 21.667600631713867f, -9.218990325927734f, 20.661399841308594f,
+ 23.487899780273438f, 0.0f, 20.661399841308594f,
+ 22.99880027770996f, -9.785409927368164f, 15.928999900817871f,
+ 24.930999755859375f, 0.0f, 15.928999900817871f,
+ 23.503799438476562f, -10.000300407409668f, 11.465299606323242f,
+ 25.4783992767334f, 0.0f, 11.465299606323242f,
+ 13.56719970703125f, -13.56719970703125f, 30.573999404907227f,
+ 15.227800369262695f, -15.227800369262695f, 25.572900772094727f,
+ 16.67639923095703f, -16.67639923095703f, 20.661399841308594f,
+ 17.701000213623047f, -17.701000213623047f, 15.928999900817871f,
+ 18.089599609375f, -18.089599609375f, 11.465299606323242f,
+ 7.500199794769287f, -17.62779998779297f, 30.573999404907227f,
+ 8.418190002441406f, -19.785400390625f, 25.572900772094727f,
+ 9.218990325927734f, -21.667600631713867f, 20.661399841308594f,
+ 9.785409927368164f, -22.99880027770996f, 15.928999900817871f,
+ 10.000300407409668f, -23.503799438476562f, 11.465299606323242f,
+ 0.0f, -19.108800888061523f, 30.573999404907227f,
+ 0.0f, -21.447599411010742f, 25.572900772094727f,
+ 0.0f, -23.487899780273438f, 20.661399841308594f,
+ 0.0f, -24.930999755859375f, 15.928999900817871f,
+ 0.0f, -25.4783992767334f, 11.465299606323242f,
+ 0.0f, -19.108800888061523f, 30.573999404907227f,
+ -7.500199794769287f, -17.62779998779297f, 30.573999404907227f,
+ -8.418190002441406f, -19.785400390625f, 25.572900772094727f,
+ 0.0f, -21.447599411010742f, 25.572900772094727f,
+ -9.218990325927734f, -21.667600631713867f, 20.661399841308594f,
+ 0.0f, -23.487899780273438f, 20.661399841308594f,
+ -9.785409927368164f, -22.99880027770996f, 15.928999900817871f,
+ 0.0f, -24.930999755859375f, 15.928999900817871f,
+ -10.000300407409668f, -23.503799438476562f, 11.465299606323242f,
+ 0.0f, -25.4783992767334f, 11.465299606323242f,
+ -13.56719970703125f, -13.56719970703125f, 30.573999404907227f,
+ -15.227800369262695f, -15.227800369262695f, 25.572900772094727f,
+ -16.67639923095703f, -16.67639923095703f, 20.661399841308594f,
+ -17.701000213623047f, -17.701000213623047f, 15.928999900817871f,
+ -18.089599609375f, -18.089599609375f, 11.465299606323242f,
+ -17.62779998779297f, -7.500199794769287f, 30.573999404907227f,
+ -19.785400390625f, -8.418190002441406f, 25.572900772094727f,
+ -21.667600631713867f, -9.218990325927734f, 20.661399841308594f,
+ -22.99880027770996f, -9.785409927368164f, 15.928999900817871f,
+ -23.503799438476562f, -10.000300407409668f, 11.465299606323242f,
+ -19.108800888061523f, 0.0f, 30.573999404907227f,
+ -21.447599411010742f, 0.0f, 25.572900772094727f,
+ -23.487899780273438f, 0.0f, 20.661399841308594f,
+ -24.930999755859375f, 0.0f, 15.928999900817871f,
+ -25.4783992767334f, 0.0f, 11.465299606323242f,
+ -19.108800888061523f, 0.0f, 30.573999404907227f,
+ -17.62779998779297f, 7.500199794769287f, 30.573999404907227f,
+ -19.785400390625f, 8.418190002441406f, 25.572900772094727f,
+ -21.447599411010742f, 0.0f, 25.572900772094727f,
+ -21.667600631713867f, 9.218990325927734f, 20.661399841308594f,
+ -23.487899780273438f, 0.0f, 20.661399841308594f,
+ -22.99880027770996f, 9.785409927368164f, 15.928999900817871f,
+ -24.930999755859375f, 0.0f, 15.928999900817871f,
+ -23.503799438476562f, 10.000300407409668f, 11.465299606323242f,
+ -25.4783992767334f, 0.0f, 11.465299606323242f,
+ -13.56719970703125f, 13.56719970703125f, 30.573999404907227f,
+ -15.227800369262695f, 15.227800369262695f, 25.572900772094727f,
+ -16.67639923095703f, 16.67639923095703f, 20.661399841308594f,
+ -17.701000213623047f, 17.701000213623047f, 15.928999900817871f,
+ -18.089599609375f, 18.089599609375f, 11.465299606323242f,
+ -7.500199794769287f, 17.62779998779297f, 30.573999404907227f,
+ -8.418190002441406f, 19.785400390625f, 25.572900772094727f,
+ -9.218990325927734f, 21.667600631713867f, 20.661399841308594f,
+ -9.785409927368164f, 22.99880027770996f, 15.928999900817871f,
+ -10.000300407409668f, 23.503799438476562f, 11.465299606323242f,
+ 0.0f, 19.108800888061523f, 30.573999404907227f,
+ 0.0f, 21.447599411010742f, 25.572900772094727f,
+ 0.0f, 23.487899780273438f, 20.661399841308594f,
+ 0.0f, 24.930999755859375f, 15.928999900817871f,
+ 0.0f, 25.4783992767334f, 11.465299606323242f,
+ 0.0f, 19.108800888061523f, 30.573999404907227f,
+ 7.500199794769287f, 17.62779998779297f, 30.573999404907227f,
+ 8.418190002441406f, 19.785400390625f, 25.572900772094727f,
+ 0.0f, 21.447599411010742f, 25.572900772094727f,
+ 9.218990325927734f, 21.667600631713867f, 20.661399841308594f,
+ 0.0f, 23.487899780273438f, 20.661399841308594f,
+ 9.785409927368164f, 22.99880027770996f, 15.928999900817871f,
+ 0.0f, 24.930999755859375f, 15.928999900817871f,
+ 10.000300407409668f, 23.503799438476562f, 11.465299606323242f,
+ 0.0f, 25.4783992767334f, 11.465299606323242f,
+ 13.56719970703125f, 13.56719970703125f, 30.573999404907227f,
+ 15.227800369262695f, 15.227800369262695f, 25.572900772094727f,
+ 16.67639923095703f, 16.67639923095703f, 20.661399841308594f,
+ 17.701000213623047f, 17.701000213623047f, 15.928999900817871f,
+ 18.089599609375f, 18.089599609375f, 11.465299606323242f,
+ 17.62779998779297f, 7.500199794769287f, 30.573999404907227f,
+ 19.785400390625f, 8.418190002441406f, 25.572900772094727f,
+ 21.667600631713867f, 9.218990325927734f, 20.661399841308594f,
+ 22.99880027770996f, 9.785409927368164f, 15.928999900817871f,
+ 23.503799438476562f, 10.000300407409668f, 11.465299606323242f,
+ 19.108800888061523f, 0.0f, 30.573999404907227f,
+ 21.447599411010742f, 0.0f, 25.572900772094727f,
+ 23.487899780273438f, 0.0f, 20.661399841308594f,
+ 24.930999755859375f, 0.0f, 15.928999900817871f,
+ 25.4783992767334f, 0.0f, 11.465299606323242f,
+ 25.4783992767334f, 0.0f, 11.465299606323242f,
+ 23.503799438476562f, -10.000300407409668f, 11.465299606323242f,
+ 22.5856990814209f, -9.609620094299316f, 7.688300132751465f,
+ 24.48310089111328f, 0.0f, 7.688300132751465f,
+ 20.565799713134766f, -8.750229835510254f, 4.89661979675293f,
+ 22.29360008239746f, 0.0f, 4.89661979675293f,
+ 18.54599952697754f, -7.890830039978027f, 3.0006699562072754f,
+ 20.104000091552734f, 0.0f, 3.0006699562072754f,
+ 17.62779998779297f, -7.500199794769287f, 1.9108799695968628f,
+ 19.108800888061523f, 0.0f, 1.9108799695968628f,
+ 18.089599609375f, -18.089599609375f, 11.465299606323242f,
+ 17.382999420166016f, -17.382999420166016f, 7.688300132751465f,
+ 15.828399658203125f, -15.828399658203125f, 4.89661979675293f,
+ 14.273900032043457f, -14.273900032043457f, 3.0006699562072754f,
+ 13.56719970703125f, -13.56719970703125f, 1.9108799695968628f,
+ 10.000300407409668f, -23.503799438476562f, 11.465299606323242f,
+ 9.609620094299316f, -22.5856990814209f, 7.688300132751465f,
+ 8.750229835510254f, -20.565799713134766f, 4.89661979675293f,
+ 7.890830039978027f, -18.54599952697754f, 3.0006699562072754f,
+ 7.500199794769287f, -17.62779998779297f, 1.9108799695968628f,
+ 0.0f, -25.4783992767334f, 11.465299606323242f,
+ 0.0f, -24.48310089111328f, 7.688300132751465f,
+ 0.0f, -22.29360008239746f, 4.89661979675293f,
+ 0.0f, -20.104000091552734f, 3.0006699562072754f,
+ 0.0f, -19.108800888061523f, 1.9108799695968628f,
+ 0.0f, -25.4783992767334f, 11.465299606323242f,
+ -10.000300407409668f, -23.503799438476562f, 11.465299606323242f,
+ -9.609620094299316f, -22.5856990814209f, 7.688300132751465f,
+ 0.0f, -24.48310089111328f, 7.688300132751465f,
+ -8.750229835510254f, -20.565799713134766f, 4.89661979675293f,
+ 0.0f, -22.29360008239746f, 4.89661979675293f,
+ -7.890830039978027f, -18.54599952697754f, 3.0006699562072754f,
+ 0.0f, -20.104000091552734f, 3.0006699562072754f,
+ -7.500199794769287f, -17.62779998779297f, 1.9108799695968628f,
+ 0.0f, -19.108800888061523f, 1.9108799695968628f,
+ -18.089599609375f, -18.089599609375f, 11.465299606323242f,
+ -17.382999420166016f, -17.382999420166016f, 7.688300132751465f,
+ -15.828399658203125f, -15.828399658203125f, 4.89661979675293f,
+ -14.273900032043457f, -14.273900032043457f, 3.0006699562072754f,
+ -13.56719970703125f, -13.56719970703125f, 1.9108799695968628f,
+ -23.503799438476562f, -10.000300407409668f, 11.465299606323242f,
+ -22.5856990814209f, -9.609620094299316f, 7.688300132751465f,
+ -20.565799713134766f, -8.750229835510254f, 4.89661979675293f,
+ -18.54599952697754f, -7.890830039978027f, 3.0006699562072754f,
+ -17.62779998779297f, -7.500199794769287f, 1.9108799695968628f,
+ -25.4783992767334f, 0.0f, 11.465299606323242f,
+ -24.48310089111328f, 0.0f, 7.688300132751465f,
+ -22.29360008239746f, 0.0f, 4.89661979675293f,
+ -20.104000091552734f, 0.0f, 3.0006699562072754f,
+ -19.108800888061523f, 0.0f, 1.9108799695968628f,
+ -25.4783992767334f, 0.0f, 11.465299606323242f,
+ -23.503799438476562f, 10.000300407409668f, 11.465299606323242f,
+ -22.5856990814209f, 9.609620094299316f, 7.688300132751465f,
+ -24.48310089111328f, 0.0f, 7.688300132751465f,
+ -20.565799713134766f, 8.750229835510254f, 4.89661979675293f,
+ -22.29360008239746f, 0.0f, 4.89661979675293f,
+ -18.54599952697754f, 7.890830039978027f, 3.0006699562072754f,
+ -20.104000091552734f, 0.0f, 3.0006699562072754f,
+ -17.62779998779297f, 7.500199794769287f, 1.9108799695968628f,
+ -19.108800888061523f, 0.0f, 1.9108799695968628f,
+ -18.089599609375f, 18.089599609375f, 11.465299606323242f,
+ -17.382999420166016f, 17.382999420166016f, 7.688300132751465f,
+ -15.828399658203125f, 15.828399658203125f, 4.89661979675293f,
+ -14.273900032043457f, 14.273900032043457f, 3.0006699562072754f,
+ -13.56719970703125f, 13.56719970703125f, 1.9108799695968628f,
+ -10.000300407409668f, 23.503799438476562f, 11.465299606323242f,
+ -9.609620094299316f, 22.5856990814209f, 7.688300132751465f,
+ -8.750229835510254f, 20.565799713134766f, 4.89661979675293f,
+ -7.890830039978027f, 18.54599952697754f, 3.0006699562072754f,
+ -7.500199794769287f, 17.62779998779297f, 1.9108799695968628f,
+ 0.0f, 25.4783992767334f, 11.465299606323242f,
+ 0.0f, 24.48310089111328f, 7.688300132751465f,
+ 0.0f, 22.29360008239746f, 4.89661979675293f,
+ 0.0f, 20.104000091552734f, 3.0006699562072754f,
+ 0.0f, 19.108800888061523f, 1.9108799695968628f,
+ 0.0f, 25.4783992767334f, 11.465299606323242f,
+ 10.000300407409668f, 23.503799438476562f, 11.465299606323242f,
+ 9.609620094299316f, 22.5856990814209f, 7.688300132751465f,
+ 0.0f, 24.48310089111328f, 7.688300132751465f,
+ 8.750229835510254f, 20.565799713134766f, 4.89661979675293f,
+ 0.0f, 22.29360008239746f, 4.89661979675293f,
+ 7.890830039978027f, 18.54599952697754f, 3.0006699562072754f,
+ 0.0f, 20.104000091552734f, 3.0006699562072754f,
+ 7.500199794769287f, 17.62779998779297f, 1.9108799695968628f,
+ 0.0f, 19.108800888061523f, 1.9108799695968628f,
+ 18.089599609375f, 18.089599609375f, 11.465299606323242f,
+ 17.382999420166016f, 17.382999420166016f, 7.688300132751465f,
+ 15.828399658203125f, 15.828399658203125f, 4.89661979675293f,
+ 14.273900032043457f, 14.273900032043457f, 3.0006699562072754f,
+ 13.56719970703125f, 13.56719970703125f, 1.9108799695968628f,
+ 23.503799438476562f, 10.000300407409668f, 11.465299606323242f,
+ 22.5856990814209f, 9.609620094299316f, 7.688300132751465f,
+ 20.565799713134766f, 8.750229835510254f, 4.89661979675293f,
+ 18.54599952697754f, 7.890830039978027f, 3.0006699562072754f,
+ 17.62779998779297f, 7.500199794769287f, 1.9108799695968628f,
+ 25.4783992767334f, 0.0f, 11.465299606323242f,
+ 24.48310089111328f, 0.0f, 7.688300132751465f,
+ 22.29360008239746f, 0.0f, 4.89661979675293f,
+ 20.104000091552734f, 0.0f, 3.0006699562072754f,
+ 19.108800888061523f, 0.0f, 1.9108799695968628f,
+ 19.108800888061523f, 0.0f, 1.9108799695968628f,
+ 17.62779998779297f, -7.500199794769287f, 1.9108799695968628f,
+ 17.228500366210938f, -7.330269813537598f, 1.2092299461364746f,
+ 18.675800323486328f, 0.0f, 1.2092299461364746f,
+ 15.093799591064453f, -6.422039985656738f, 0.5971490144729614f,
+ 16.361900329589844f, 0.0f, 0.5971490144729614f,
+ 9.819259643554688f, -4.177840232849121f, 0.16421599686145782f,
+ 10.644200325012207f, 0.0f, 0.16421599686145782f,
+ 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f,
+ 13.56719970703125f, -13.56719970703125f, 1.9108799695968628f,
+ 13.25979995727539f, -13.25979995727539f, 1.2092299461364746f,
+ 11.616900444030762f, -11.616900444030762f, 0.5971490144729614f,
+ 7.557370185852051f, -7.557370185852051f, 0.16421599686145782f,
+ 0.0f, 0.0f, 0.0f,
+ 7.500199794769287f, -17.62779998779297f, 1.9108799695968628f,
+ 7.330269813537598f, -17.228500366210938f, 1.2092299461364746f,
+ 6.422039985656738f, -15.093799591064453f, 0.5971490144729614f,
+ 4.177840232849121f, -9.819259643554688f, 0.16421599686145782f,
+ 0.0f, 0.0f, 0.0f,
+ 0.0f, -19.108800888061523f, 1.9108799695968628f,
+ 0.0f, -18.675800323486328f, 1.2092299461364746f,
+ 0.0f, -16.361900329589844f, 0.5971490144729614f,
+ 0.0f, -10.644200325012207f, 0.16421599686145782f,
+ 0.0f, 0.0f, 0.0f,
+ 0.0f, -19.108800888061523f, 1.9108799695968628f,
+ -7.500199794769287f, -17.62779998779297f, 1.9108799695968628f,
+ -7.330269813537598f, -17.228500366210938f, 1.2092299461364746f,
+ 0.0f, -18.675800323486328f, 1.2092299461364746f,
+ -6.422039985656738f, -15.093799591064453f, 0.5971490144729614f,
+ 0.0f, -16.361900329589844f, 0.5971490144729614f,
+ -4.177840232849121f, -9.819259643554688f, 0.16421599686145782f,
+ 0.0f, -10.644200325012207f, 0.16421599686145782f,
+ 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f,
+ -13.56719970703125f, -13.56719970703125f, 1.9108799695968628f,
+ -13.25979995727539f, -13.25979995727539f, 1.2092299461364746f,
+ -11.616900444030762f, -11.616900444030762f, 0.5971490144729614f,
+ -7.557370185852051f, -7.557370185852051f, 0.16421599686145782f,
+ 0.0f, 0.0f, 0.0f,
+ -17.62779998779297f, -7.500199794769287f, 1.9108799695968628f,
+ -17.228500366210938f, -7.330269813537598f, 1.2092299461364746f,
+ -15.093799591064453f, -6.422039985656738f, 0.5971490144729614f,
+ -9.819259643554688f, -4.177840232849121f, 0.16421599686145782f,
+ 0.0f, 0.0f, 0.0f,
+ -19.108800888061523f, 0.0f, 1.9108799695968628f,
+ -18.675800323486328f, 0.0f, 1.2092299461364746f,
+ -16.361900329589844f, 0.0f, 0.5971490144729614f,
+ -10.644200325012207f, 0.0f, 0.16421599686145782f,
+ 0.0f, 0.0f, 0.0f,
+ -19.108800888061523f, 0.0f, 1.9108799695968628f,
+ -17.62779998779297f, 7.500199794769287f, 1.9108799695968628f,
+ -17.228500366210938f, 7.330269813537598f, 1.2092299461364746f,
+ -18.675800323486328f, 0.0f, 1.2092299461364746f,
+ -15.093799591064453f, 6.422039985656738f, 0.5971490144729614f,
+ -16.361900329589844f, 0.0f, 0.5971490144729614f,
+ -9.819259643554688f, 4.177840232849121f, 0.16421599686145782f,
+ -10.644200325012207f, 0.0f, 0.16421599686145782f,
+ 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f,
+ -13.56719970703125f, 13.56719970703125f, 1.9108799695968628f,
+ -13.25979995727539f, 13.25979995727539f, 1.2092299461364746f,
+ -11.616900444030762f, 11.616900444030762f, 0.5971490144729614f,
+ -7.557370185852051f, 7.557370185852051f, 0.16421599686145782f,
+ 0.0f, 0.0f, 0.0f,
+ -7.500199794769287f, 17.62779998779297f, 1.9108799695968628f,
+ -7.330269813537598f, 17.228500366210938f, 1.2092299461364746f,
+ -6.422039985656738f, 15.093799591064453f, 0.5971490144729614f,
+ -4.177840232849121f, 9.819259643554688f, 0.16421599686145782f,
+ 0.0f, 0.0f, 0.0f,
+ 0.0f, 19.108800888061523f, 1.9108799695968628f,
+ 0.0f, 18.675800323486328f, 1.2092299461364746f,
+ 0.0f, 16.361900329589844f, 0.5971490144729614f,
+ 0.0f, 10.644200325012207f, 0.16421599686145782f,
+ 0.0f, 0.0f, 0.0f,
+ 0.0f, 19.108800888061523f, 1.9108799695968628f,
+ 7.500199794769287f, 17.62779998779297f, 1.9108799695968628f,
+ 7.330269813537598f, 17.228500366210938f, 1.2092299461364746f,
+ 0.0f, 18.675800323486328f, 1.2092299461364746f,
+ 6.422039985656738f, 15.093799591064453f, 0.5971490144729614f,
+ 0.0f, 16.361900329589844f, 0.5971490144729614f,
+ 4.177840232849121f, 9.819259643554688f, 0.16421599686145782f,
+ 0.0f, 10.644200325012207f, 0.16421599686145782f,
+ 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f,
+ 13.56719970703125f, 13.56719970703125f, 1.9108799695968628f,
+ 13.25979995727539f, 13.25979995727539f, 1.2092299461364746f,
+ 11.616900444030762f, 11.616900444030762f, 0.5971490144729614f,
+ 7.557370185852051f, 7.557370185852051f, 0.16421599686145782f,
+ 0.0f, 0.0f, 0.0f,
+ 17.62779998779297f, 7.500199794769287f, 1.9108799695968628f,
+ 17.228500366210938f, 7.330269813537598f, 1.2092299461364746f,
+ 15.093799591064453f, 6.422039985656738f, 0.5971490144729614f,
+ 9.819259643554688f, 4.177840232849121f, 0.16421599686145782f,
+ 0.0f, 0.0f, 0.0f,
+ 19.108800888061523f, 0.0f, 1.9108799695968628f,
+ 18.675800323486328f, 0.0f, 1.2092299461364746f,
+ 16.361900329589844f, 0.0f, 0.5971490144729614f,
+ 10.644200325012207f, 0.0f, 0.16421599686145782f,
+ 0.0f, 0.0f, 0.0f,
+ -20.382699966430664f, 0.0f, 25.796899795532227f,
+ -20.1835994720459f, -2.149739980697632f, 26.244699478149414f,
+ -26.511600494384766f, -2.149739980697632f, 26.192899703979492f,
+ -26.334299087524414f, 0.0f, 25.752099990844727f,
+ -31.156299591064453f, -2.149739980697632f, 25.830400466918945f,
+ -30.733299255371094f, 0.0f, 25.438600540161133f,
+ -34.016998291015625f, -2.149739980697632f, 24.846500396728516f,
+ -33.46030044555664f, 0.0f, 24.587600708007812f,
+ -34.99290084838867f, -2.149739980697632f, 22.930500030517578f,
+ -34.39580154418945f, 0.0f, 22.930500030517578f,
+ -19.74570083618164f, -2.8663198947906494f, 27.229999542236328f,
+ -26.901599884033203f, -2.8663198947906494f, 27.162799835205078f,
+ -32.08679962158203f, -2.8663198947906494f, 26.69260025024414f,
+ -35.241798400878906f, -2.8663198947906494f, 25.416200637817383f,
+ -36.30670166015625f, -2.8663198947906494f, 22.930500030517578f,
+ -19.30780029296875f, -2.149739980697632f, 28.215299606323242f,
+ -27.29159927368164f, -2.149739980697632f, 28.132699966430664f,
+ -33.017398834228516f, -2.149739980697632f, 27.55470085144043f,
+ -36.46649932861328f, -2.149739980697632f, 25.98579978942871f,
+ -37.620399475097656f, -2.149739980697632f, 22.930500030517578f,
+ -19.108800888061523f, 0.0f, 28.66320037841797f,
+ -27.468900680541992f, 0.0f, 28.57360076904297f,
+ -33.440399169921875f, 0.0f, 27.94659996032715f,
+ -37.02330017089844f, 0.0f, 26.244699478149414f,
+ -38.21760177612305f, 0.0f, 22.930500030517578f,
+ -19.108800888061523f, 0.0f, 28.66320037841797f,
+ -19.30780029296875f, 2.149739980697632f, 28.215299606323242f,
+ -27.29159927368164f, 2.149739980697632f, 28.132699966430664f,
+ -27.468900680541992f, 0.0f, 28.57360076904297f,
+ -33.017398834228516f, 2.149739980697632f, 27.55470085144043f,
+ -33.440399169921875f, 0.0f, 27.94659996032715f,
+ -36.46649932861328f, 2.149739980697632f, 25.98579978942871f,
+ -37.02330017089844f, 0.0f, 26.244699478149414f,
+ -37.620399475097656f, 2.149739980697632f, 22.930500030517578f,
+ -38.21760177612305f, 0.0f, 22.930500030517578f,
+ -19.74570083618164f, 2.8663198947906494f, 27.229999542236328f,
+ -26.901599884033203f, 2.8663198947906494f, 27.162799835205078f,
+ -32.08679962158203f, 2.8663198947906494f, 26.69260025024414f,
+ -35.241798400878906f, 2.8663198947906494f, 25.416200637817383f,
+ -36.30670166015625f, 2.8663198947906494f, 22.930500030517578f,
+ -20.1835994720459f, 2.149739980697632f, 26.244699478149414f,
+ -26.511600494384766f, 2.149739980697632f, 26.192899703979492f,
+ -31.156299591064453f, 2.149739980697632f, 25.830400466918945f,
+ -34.016998291015625f, 2.149739980697632f, 24.846500396728516f,
+ -34.99290084838867f, 2.149739980697632f, 22.930500030517578f,
+ -20.382699966430664f, 0.0f, 25.796899795532227f,
+ -26.334299087524414f, 0.0f, 25.752099990844727f,
+ -30.733299255371094f, 0.0f, 25.438600540161133f,
+ -33.46030044555664f, 0.0f, 24.587600708007812f,
+ -34.39580154418945f, 0.0f, 22.930500030517578f,
+ -34.39580154418945f, 0.0f, 22.930500030517578f,
+ -34.99290084838867f, -2.149739980697632f, 22.930500030517578f,
+ -34.44089889526367f, -2.149739980697632f, 20.082199096679688f,
+ -33.89820098876953f, 0.0f, 20.33289909362793f,
+ -32.711299896240234f, -2.149739980697632f, 16.81529998779297f,
+ -32.32569885253906f, 0.0f, 17.197900772094727f,
+ -29.69420051574707f, -2.149739980697632f, 13.590499877929688f,
+ -29.558900833129883f, 0.0f, 14.062899589538574f,
+ -25.279300689697266f, -2.149739980697632f, 10.8681001663208f,
+ -25.4783992767334f, 0.0f, 11.465299606323242f,
+ -36.30670166015625f, -2.8663198947906494f, 22.930500030517578f,
+ -35.6348991394043f, -2.8663198947906494f, 19.530500411987305f,
+ -33.55979919433594f, -2.8663198947906494f, 15.973699569702148f,
+ -29.99180030822754f, -2.8663198947906494f, 12.551300048828125f,
+ -24.841400146484375f, -2.8663198947906494f, 9.554389953613281f,
+ -37.620399475097656f, -2.149739980697632f, 22.930500030517578f,
+ -36.82889938354492f, -2.149739980697632f, 18.97879981994629f,
+ -34.408199310302734f, -2.149739980697632f, 15.132100105285645f,
+ -30.289499282836914f, -2.149739980697632f, 11.512200355529785f,
+ -24.403499603271484f, -2.149739980697632f, 8.240659713745117f,
+ -38.21760177612305f, 0.0f, 22.930500030517578f,
+ -37.37160110473633f, 0.0f, 18.728099822998047f,
+ -34.79389953613281f, 0.0f, 14.749600410461426f,
+ -30.424800872802734f, 0.0f, 11.039799690246582f,
+ -24.204500198364258f, 0.0f, 7.643509864807129f,
+ -38.21760177612305f, 0.0f, 22.930500030517578f,
+ -37.620399475097656f, 2.149739980697632f, 22.930500030517578f,
+ -36.82889938354492f, 2.149739980697632f, 18.97879981994629f,
+ -37.37160110473633f, 0.0f, 18.728099822998047f,
+ -34.408199310302734f, 2.149739980697632f, 15.132100105285645f,
+ -34.79389953613281f, 0.0f, 14.749600410461426f,
+ -30.289499282836914f, 2.149739980697632f, 11.512200355529785f,
+ -30.424800872802734f, 0.0f, 11.039799690246582f,
+ -24.403499603271484f, 2.149739980697632f, 8.240659713745117f,
+ -24.204500198364258f, 0.0f, 7.643509864807129f,
+ -36.30670166015625f, 2.8663198947906494f, 22.930500030517578f,
+ -35.6348991394043f, 2.8663198947906494f, 19.530500411987305f,
+ -33.55979919433594f, 2.8663198947906494f, 15.973699569702148f,
+ -29.99180030822754f, 2.8663198947906494f, 12.551300048828125f,
+ -24.841400146484375f, 2.8663198947906494f, 9.554389953613281f,
+ -34.99290084838867f, 2.149739980697632f, 22.930500030517578f,
+ -34.44089889526367f, 2.149739980697632f, 20.082199096679688f,
+ -32.711299896240234f, 2.149739980697632f, 16.81529998779297f,
+ -29.69420051574707f, 2.149739980697632f, 13.590499877929688f,
+ -25.279300689697266f, 2.149739980697632f, 10.8681001663208f,
+ -34.39580154418945f, 0.0f, 22.930500030517578f,
+ -33.89820098876953f, 0.0f, 20.33289909362793f,
+ -32.32569885253906f, 0.0f, 17.197900772094727f,
+ -29.558900833129883f, 0.0f, 14.062899589538574f,
+ -25.4783992767334f, 0.0f, 11.465299606323242f,
+ 21.656600952148438f, 0.0f, 18.15329933166504f,
+ 21.656600952148438f, -4.729420185089111f, 16.511199951171875f,
+ 28.233999252319336f, -4.270359992980957f, 18.339000701904297f,
+ 27.76740074157715f, 0.0f, 19.55660057067871f,
+ 31.011899948120117f, -3.2604401111602783f, 22.221399307250977f,
+ 30.4148006439209f, 0.0f, 22.930500030517578f,
+ 32.59560012817383f, -2.2505099773406982f, 26.764400482177734f,
+ 31.867900848388672f, 0.0f, 27.020999908447266f,
+ 35.5900993347168f, -1.791450023651123f, 30.573999404907227f,
+ 34.39580154418945f, 0.0f, 30.573999404907227f,
+ 21.656600952148438f, -6.3059000968933105f, 12.89840030670166f,
+ 29.260299682617188f, -5.693819999694824f, 15.660200119018555f,
+ 32.32569885253906f, -4.347249984741211f, 20.661399841308594f,
+ 34.19670104980469f, -3.0006699562072754f, 26.199899673461914f,
+ 38.21760177612305f, -2.3886001110076904f, 30.573999404907227f,
+ 21.656600952148438f, -4.729420185089111f, 9.285670280456543f,
+ 30.286699295043945f, -4.270359992980957f, 12.981499671936035f,
+ 33.639400482177734f, -3.2604401111602783f, 19.101299285888672f,
+ 35.79790115356445f, -2.2505099773406982f, 25.635400772094727f,
+ 40.845001220703125f, -1.791450023651123f, 30.573999404907227f,
+ 21.656600952148438f, 0.0f, 7.643509864807129f,
+ 30.75320053100586f, 0.0f, 11.763799667358398f,
+ 34.23659896850586f, 0.0f, 18.392200469970703f,
+ 36.52560043334961f, 0.0f, 25.378799438476562f,
+ 42.03929901123047f, 0.0f, 30.573999404907227f,
+ 21.656600952148438f, 0.0f, 7.643509864807129f,
+ 21.656600952148438f, 4.729420185089111f, 9.285670280456543f,
+ 30.286699295043945f, 4.270359992980957f, 12.981499671936035f,
+ 30.75320053100586f, 0.0f, 11.763799667358398f,
+ 33.639400482177734f, 3.2604401111602783f, 19.101299285888672f,
+ 34.23659896850586f, 0.0f, 18.392200469970703f,
+ 35.79790115356445f, 2.2505099773406982f, 25.635400772094727f,
+ 36.52560043334961f, 0.0f, 25.378799438476562f,
+ 40.845001220703125f, 1.791450023651123f, 30.573999404907227f,
+ 42.03929901123047f, 0.0f, 30.573999404907227f,
+ 21.656600952148438f, 6.3059000968933105f, 12.89840030670166f,
+ 29.260299682617188f, 5.693819999694824f, 15.660200119018555f,
+ 32.32569885253906f, 4.347249984741211f, 20.661399841308594f,
+ 34.19670104980469f, 3.0006699562072754f, 26.199899673461914f,
+ 38.21760177612305f, 2.3886001110076904f, 30.573999404907227f,
+ 21.656600952148438f, 4.729420185089111f, 16.511199951171875f,
+ 28.233999252319336f, 4.270359992980957f, 18.339000701904297f,
+ 31.011899948120117f, 3.2604401111602783f, 22.221399307250977f,
+ 32.59560012817383f, 2.2505099773406982f, 26.764400482177734f,
+ 35.5900993347168f, 1.791450023651123f, 30.573999404907227f,
+ 21.656600952148438f, 0.0f, 18.15329933166504f,
+ 27.76740074157715f, 0.0f, 19.55660057067871f,
+ 30.4148006439209f, 0.0f, 22.930500030517578f,
+ 31.867900848388672f, 0.0f, 27.020999908447266f,
+ 34.39580154418945f, 0.0f, 30.573999404907227f,
+ 34.39580154418945f, 0.0f, 30.573999404907227f,
+ 35.5900993347168f, -1.791450023651123f, 30.573999404907227f,
+ 36.59049987792969f, -1.679479956626892f, 31.137699127197266f,
+ 35.3114013671875f, 0.0f, 31.111499786376953f,
+ 37.18870162963867f, -1.4331599473953247f, 31.332599639892578f,
+ 35.98820114135742f, 0.0f, 31.290599822998047f,
+ 37.206600189208984f, -1.1868300437927246f, 31.1481990814209f,
+ 36.187198638916016f, 0.0f, 31.111499786376953f,
+ 36.46590042114258f, -1.074869990348816f, 30.573999404907227f,
+ 35.669700622558594f, 0.0f, 30.573999404907227f,
+ 38.21760177612305f, -2.3886001110076904f, 30.573999404907227f,
+ 39.40439987182617f, -2.2393100261688232f, 31.195499420166016f,
+ 39.829898834228516f, -1.9108799695968628f, 31.424999237060547f,
+ 39.44919967651367f, -1.582450032234192f, 31.229000091552734f,
+ 38.21760177612305f, -1.4331599473953247f, 30.573999404907227f,
+ 40.845001220703125f, -1.791450023651123f, 30.573999404907227f,
+ 42.218299865722656f, -1.679479956626892f, 31.25320053100586f,
+ 42.47100067138672f, -1.4331599473953247f, 31.51740074157715f,
+ 41.69169998168945f, -1.1868300437927246f, 31.309900283813477f,
+ 39.969200134277344f, -1.074869990348816f, 30.573999404907227f,
+ 42.03929901123047f, 0.0f, 30.573999404907227f,
+ 43.49729919433594f, 0.0f, 31.279399871826172f,
+ 43.67150115966797f, 0.0f, 31.55929946899414f,
+ 42.71110153198242f, 0.0f, 31.346599578857422f,
+ 40.76539993286133f, 0.0f, 30.573999404907227f,
+ 42.03929901123047f, 0.0f, 30.573999404907227f,
+ 40.845001220703125f, 1.791450023651123f, 30.573999404907227f,
+ 42.218299865722656f, 1.679479956626892f, 31.25320053100586f,
+ 43.49729919433594f, 0.0f, 31.279399871826172f,
+ 42.47100067138672f, 1.4331599473953247f, 31.51740074157715f,
+ 43.67150115966797f, 0.0f, 31.55929946899414f,
+ 41.69169998168945f, 1.1868300437927246f, 31.309900283813477f,
+ 42.71110153198242f, 0.0f, 31.346599578857422f,
+ 39.969200134277344f, 1.074869990348816f, 30.573999404907227f,
+ 40.76539993286133f, 0.0f, 30.573999404907227f,
+ 38.21760177612305f, 2.3886001110076904f, 30.573999404907227f,
+ 39.40439987182617f, 2.2393100261688232f, 31.195499420166016f,
+ 39.829898834228516f, 1.9108799695968628f, 31.424999237060547f,
+ 39.44919967651367f, 1.582450032234192f, 31.229000091552734f,
+ 38.21760177612305f, 1.4331599473953247f, 30.573999404907227f,
+ 35.5900993347168f, 1.791450023651123f, 30.573999404907227f,
+ 36.59049987792969f, 1.679479956626892f, 31.137699127197266f,
+ 37.18870162963867f, 1.4331599473953247f, 31.332599639892578f,
+ 37.206600189208984f, 1.1868300437927246f, 31.1481990814209f,
+ 36.46590042114258f, 1.074869990348816f, 30.573999404907227f,
+ 34.39580154418945f, 0.0f, 30.573999404907227f,
+ 35.3114013671875f, 0.0f, 31.111499786376953f,
+ 35.98820114135742f, 0.0f, 31.290599822998047f,
+ 36.187198638916016f, 0.0f, 31.111499786376953f,
+ 35.669700622558594f, 0.0f, 30.573999404907227f,
+ 0.0f, 0.0f, 40.12839889526367f,
+ 0.0f, 0.0f, 40.12839889526367f,
+ 4.004499912261963f, -1.7077000141143799f, 39.501399993896484f,
+ 4.339280128479004f, 0.0f, 39.501399993896484f,
+ 3.8207099437713623f, -1.6290700435638428f, 37.97869873046875f,
+ 4.140230178833008f, 0.0f, 37.97869873046875f,
+ 2.314160108566284f, -0.985912024974823f, 36.09769821166992f,
+ 2.5080299377441406f, 0.0f, 36.09769821166992f,
+ 2.3503799438476562f, -1.0000300407409668f, 34.39580154418945f,
+ 2.547840118408203f, 0.0f, 34.39580154418945f,
+ 0.0f, 0.0f, 40.12839889526367f,
+ 3.0849199295043945f, -3.0849199295043945f, 39.501399993896484f,
+ 2.943150043487549f, -2.943150043487549f, 37.97869873046875f,
+ 1.782039999961853f, -1.782039999961853f, 36.09769821166992f,
+ 1.8089599609375f, -1.8089599609375f, 34.39580154418945f,
+ 0.0f, 0.0f, 40.12839889526367f,
+ 1.7077000141143799f, -4.004499912261963f, 39.501399993896484f,
+ 1.6290700435638428f, -3.8207099437713623f, 37.97869873046875f,
+ 0.985912024974823f, -2.314160108566284f, 36.09769821166992f,
+ 1.0000300407409668f, -2.3503799438476562f, 34.39580154418945f,
+ 0.0f, 0.0f, 40.12839889526367f,
+ 0.0f, -4.339280128479004f, 39.501399993896484f,
+ 0.0f, -4.140230178833008f, 37.97869873046875f,
+ 0.0f, -2.5080299377441406f, 36.09769821166992f,
+ 0.0f, -2.547840118408203f, 34.39580154418945f,
+ 0.0f, 0.0f, 40.12839889526367f,
+ 0.0f, 0.0f, 40.12839889526367f,
+ -1.7077000141143799f, -4.004499912261963f, 39.501399993896484f,
+ 0.0f, -4.339280128479004f, 39.501399993896484f,
+ -1.6290700435638428f, -3.8207099437713623f, 37.97869873046875f,
+ 0.0f, -4.140230178833008f, 37.97869873046875f,
+ -0.985912024974823f, -2.314160108566284f, 36.09769821166992f,
+ 0.0f, -2.5080299377441406f, 36.09769821166992f,
+ -1.0000300407409668f, -2.3503799438476562f, 34.39580154418945f,
+ 0.0f, -2.547840118408203f, 34.39580154418945f,
+ 0.0f, 0.0f, 40.12839889526367f,
+ -3.0849199295043945f, -3.0849199295043945f, 39.501399993896484f,
+ -2.943150043487549f, -2.943150043487549f, 37.97869873046875f,
+ -1.782039999961853f, -1.782039999961853f, 36.09769821166992f,
+ -1.8089599609375f, -1.8089599609375f, 34.39580154418945f,
+ 0.0f, 0.0f, 40.12839889526367f,
+ -4.004499912261963f, -1.7077000141143799f, 39.501399993896484f,
+ -3.8207099437713623f, -1.6290700435638428f, 37.97869873046875f,
+ -2.314160108566284f, -0.985912024974823f, 36.09769821166992f,
+ -2.3503799438476562f, -1.0000300407409668f, 34.39580154418945f,
+ 0.0f, 0.0f, 40.12839889526367f,
+ -4.339280128479004f, 0.0f, 39.501399993896484f,
+ -4.140230178833008f, 0.0f, 37.97869873046875f,
+ -2.5080299377441406f, 0.0f, 36.09769821166992f,
+ -2.547840118408203f, 0.0f, 34.39580154418945f,
+ 0.0f, 0.0f, 40.12839889526367f,
+ 0.0f, 0.0f, 40.12839889526367f,
+ -4.004499912261963f, 1.7077000141143799f, 39.501399993896484f,
+ -4.339280128479004f, 0.0f, 39.501399993896484f,
+ -3.8207099437713623f, 1.6290700435638428f, 37.97869873046875f,
+ -4.140230178833008f, 0.0f, 37.97869873046875f,
+ -2.314160108566284f, 0.985912024974823f, 36.09769821166992f,
+ -2.5080299377441406f, 0.0f, 36.09769821166992f,
+ -2.3503799438476562f, 1.0000300407409668f, 34.39580154418945f,
+ -2.547840118408203f, 0.0f, 34.39580154418945f,
+ 0.0f, 0.0f, 40.12839889526367f,
+ -3.0849199295043945f, 3.0849199295043945f, 39.501399993896484f,
+ -2.943150043487549f, 2.943150043487549f, 37.97869873046875f,
+ -1.782039999961853f, 1.782039999961853f, 36.09769821166992f,
+ -1.8089599609375f, 1.8089599609375f, 34.39580154418945f,
+ 0.0f, 0.0f, 40.12839889526367f,
+ -1.7077000141143799f, 4.004499912261963f, 39.501399993896484f,
+ -1.6290700435638428f, 3.8207099437713623f, 37.97869873046875f,
+ -0.985912024974823f, 2.314160108566284f, 36.09769821166992f,
+ -1.0000300407409668f, 2.3503799438476562f, 34.39580154418945f,
+ 0.0f, 0.0f, 40.12839889526367f,
+ 0.0f, 4.339280128479004f, 39.501399993896484f,
+ 0.0f, 4.140230178833008f, 37.97869873046875f,
+ 0.0f, 2.5080299377441406f, 36.09769821166992f,
+ 0.0f, 2.547840118408203f, 34.39580154418945f,
+ 0.0f, 0.0f, 40.12839889526367f,
+ 0.0f, 0.0f, 40.12839889526367f,
+ 1.7077000141143799f, 4.004499912261963f, 39.501399993896484f,
+ 0.0f, 4.339280128479004f, 39.501399993896484f,
+ 1.6290700435638428f, 3.8207099437713623f, 37.97869873046875f,
+ 0.0f, 4.140230178833008f, 37.97869873046875f,
+ 0.985912024974823f, 2.314160108566284f, 36.09769821166992f,
+ 0.0f, 2.5080299377441406f, 36.09769821166992f,
+ 1.0000300407409668f, 2.3503799438476562f, 34.39580154418945f,
+ 0.0f, 2.547840118408203f, 34.39580154418945f,
+ 0.0f, 0.0f, 40.12839889526367f,
+ 3.0849199295043945f, 3.0849199295043945f, 39.501399993896484f,
+ 2.943150043487549f, 2.943150043487549f, 37.97869873046875f,
+ 1.782039999961853f, 1.782039999961853f, 36.09769821166992f,
+ 1.8089599609375f, 1.8089599609375f, 34.39580154418945f,
+ 0.0f, 0.0f, 40.12839889526367f,
+ 4.004499912261963f, 1.7077000141143799f, 39.501399993896484f,
+ 3.8207099437713623f, 1.6290700435638428f, 37.97869873046875f,
+ 2.314160108566284f, 0.985912024974823f, 36.09769821166992f,
+ 2.3503799438476562f, 1.0000300407409668f, 34.39580154418945f,
+ 0.0f, 0.0f, 40.12839889526367f,
+ 4.339280128479004f, 0.0f, 39.501399993896484f,
+ 4.140230178833008f, 0.0f, 37.97869873046875f,
+ 2.5080299377441406f, 0.0f, 36.09769821166992f,
+ 2.547840118408203f, 0.0f, 34.39580154418945f,
+ 2.547840118408203f, 0.0f, 34.39580154418945f,
+ 2.3503799438476562f, -1.0000300407409668f, 34.39580154418945f,
+ 5.361800193786621f, -2.2813100814819336f, 33.261199951171875f,
+ 5.812250137329102f, 0.0f, 33.261199951171875f,
+ 9.695320129394531f, -4.125110149383545f, 32.484901428222656f,
+ 10.50979995727539f, 0.0f, 32.484901428222656f,
+ 13.58810043334961f, -5.781400203704834f, 31.708599090576172f,
+ 14.729700088500977f, 0.0f, 31.708599090576172f,
+ 15.27750015258789f, -6.5001702308654785f, 30.573999404907227f,
+ 16.56089973449707f, 0.0f, 30.573999404907227f,
+ 1.8089599609375f, -1.8089599609375f, 34.39580154418945f,
+ 4.126699924468994f, -4.126699924468994f, 33.261199951171875f,
+ 7.461979866027832f, -7.461979866027832f, 32.484901428222656f,
+ 10.458100318908691f, -10.458100318908691f, 31.708599090576172f,
+ 11.758299827575684f, -11.758299827575684f, 30.573999404907227f,
+ 1.0000300407409668f, -2.3503799438476562f, 34.39580154418945f,
+ 2.2813100814819336f, -5.361800193786621f, 33.261199951171875f,
+ 4.125110149383545f, -9.695320129394531f, 32.484901428222656f,
+ 5.781400203704834f, -13.58810043334961f, 31.708599090576172f,
+ 6.5001702308654785f, -15.27750015258789f, 30.573999404907227f,
+ 0.0f, -2.547840118408203f, 34.39580154418945f,
+ 0.0f, -5.812250137329102f, 33.261199951171875f,
+ 0.0f, -10.50979995727539f, 32.484901428222656f,
+ 0.0f, -14.729700088500977f, 31.708599090576172f,
+ 0.0f, -16.56089973449707f, 30.573999404907227f,
+ 0.0f, -2.547840118408203f, 34.39580154418945f,
+ -1.0000300407409668f, -2.3503799438476562f, 34.39580154418945f,
+ -2.2813100814819336f, -5.361800193786621f, 33.261199951171875f,
+ 0.0f, -5.812250137329102f, 33.261199951171875f,
+ -4.125110149383545f, -9.695320129394531f, 32.484901428222656f,
+ 0.0f, -10.50979995727539f, 32.484901428222656f,
+ -5.781400203704834f, -13.58810043334961f, 31.708599090576172f,
+ 0.0f, -14.729700088500977f, 31.708599090576172f,
+ -6.5001702308654785f, -15.27750015258789f, 30.573999404907227f,
+ 0.0f, -16.56089973449707f, 30.573999404907227f,
+ -1.8089599609375f, -1.8089599609375f, 34.39580154418945f,
+ -4.126699924468994f, -4.126699924468994f, 33.261199951171875f,
+ -7.461979866027832f, -7.461979866027832f, 32.484901428222656f,
+ -10.458100318908691f, -10.458100318908691f, 31.708599090576172f,
+ -11.758299827575684f, -11.758299827575684f, 30.573999404907227f,
+ -2.3503799438476562f, -1.0000300407409668f, 34.39580154418945f,
+ -5.361800193786621f, -2.2813100814819336f, 33.261199951171875f,
+ -9.695320129394531f, -4.125110149383545f, 32.484901428222656f,
+ -13.58810043334961f, -5.781400203704834f, 31.708599090576172f,
+ -15.27750015258789f, -6.5001702308654785f, 30.573999404907227f,
+ -2.547840118408203f, 0.0f, 34.39580154418945f,
+ -5.812250137329102f, 0.0f, 33.261199951171875f,
+ -10.50979995727539f, 0.0f, 32.484901428222656f,
+ -14.729700088500977f, 0.0f, 31.708599090576172f,
+ -16.56089973449707f, 0.0f, 30.573999404907227f,
+ -2.547840118408203f, 0.0f, 34.39580154418945f,
+ -2.3503799438476562f, 1.0000300407409668f, 34.39580154418945f,
+ -5.361800193786621f, 2.2813100814819336f, 33.261199951171875f,
+ -5.812250137329102f, 0.0f, 33.261199951171875f,
+ -9.695320129394531f, 4.125110149383545f, 32.484901428222656f,
+ -10.50979995727539f, 0.0f, 32.484901428222656f,
+ -13.58810043334961f, 5.781400203704834f, 31.708599090576172f,
+ -14.729700088500977f, 0.0f, 31.708599090576172f,
+ -15.27750015258789f, 6.5001702308654785f, 30.573999404907227f,
+ -16.56089973449707f, 0.0f, 30.573999404907227f,
+ -1.8089599609375f, 1.8089599609375f, 34.39580154418945f,
+ -4.126699924468994f, 4.126699924468994f, 33.261199951171875f,
+ -7.461979866027832f, 7.461979866027832f, 32.484901428222656f,
+ -10.458100318908691f, 10.458100318908691f, 31.708599090576172f,
+ -11.758299827575684f, 11.758299827575684f, 30.573999404907227f,
+ -1.0000300407409668f, 2.3503799438476562f, 34.39580154418945f,
+ -2.2813100814819336f, 5.361800193786621f, 33.261199951171875f,
+ -4.125110149383545f, 9.695320129394531f, 32.484901428222656f,
+ -5.781400203704834f, 13.58810043334961f, 31.708599090576172f,
+ -6.5001702308654785f, 15.27750015258789f, 30.573999404907227f,
+ 0.0f, 2.547840118408203f, 34.39580154418945f,
+ 0.0f, 5.812250137329102f, 33.261199951171875f,
+ 0.0f, 10.50979995727539f, 32.484901428222656f,
+ 0.0f, 14.729700088500977f, 31.708599090576172f,
+ 0.0f, 16.56089973449707f, 30.573999404907227f,
+ 0.0f, 2.547840118408203f, 34.39580154418945f,
+ 1.0000300407409668f, 2.3503799438476562f, 34.39580154418945f,
+ 2.2813100814819336f, 5.361800193786621f, 33.261199951171875f,
+ 0.0f, 5.812250137329102f, 33.261199951171875f,
+ 4.125110149383545f, 9.695320129394531f, 32.484901428222656f,
+ 0.0f, 10.50979995727539f, 32.484901428222656f,
+ 5.781400203704834f, 13.58810043334961f, 31.708599090576172f,
+ 0.0f, 14.729700088500977f, 31.708599090576172f,
+ 6.5001702308654785f, 15.27750015258789f, 30.573999404907227f,
+ 0.0f, 16.56089973449707f, 30.573999404907227f,
+ 1.8089599609375f, 1.8089599609375f, 34.39580154418945f,
+ 4.126699924468994f, 4.126699924468994f, 33.261199951171875f,
+ 7.461979866027832f, 7.461979866027832f, 32.484901428222656f,
+ 10.458100318908691f, 10.458100318908691f, 31.708599090576172f,
+ 11.758299827575684f, 11.758299827575684f, 30.573999404907227f,
+ 2.3503799438476562f, 1.0000300407409668f, 34.39580154418945f,
+ 5.361800193786621f, 2.2813100814819336f, 33.261199951171875f,
+ 9.695320129394531f, 4.125110149383545f, 32.484901428222656f,
+ 13.58810043334961f, 5.781400203704834f, 31.708599090576172f,
+ 15.27750015258789f, 6.5001702308654785f, 30.573999404907227f,
+ 2.547840118408203f, 0.0f, 34.39580154418945f,
+ 5.812250137329102f, 0.0f, 33.261199951171875f,
+ 10.50979995727539f, 0.0f, 32.484901428222656f,
+ 14.729700088500977f, 0.0f, 31.708599090576172f,
+ 16.56089973449707f, 0.0f, 30.573999404907227f,
+};
+
+static const float teapot_normals[] = {
+ -0.9667419791221619, 0, -0.25575199723243713,
+ -0.8930140137672424, 0.3698819875717163, -0.2563450038433075,
+ -0.8934370279312134, 0.36910200119018555, 0.2559970021247864,
+ -0.9668239951133728, 0, 0.2554430067539215,
+ -0.0838799998164177, 0.03550700098276138, 0.9958429932594299,
+ -0.09205400198698044, 0, 0.9957540035247803,
+ 0.629721999168396, -0.2604379951953888, 0.7318620085716248,
+ 0.6820489764213562, 0, 0.7313070297241211,
+ 0.803725004196167, -0.3325839936733246, 0.4933690130710602,
+ 0.8703010082244873, 0, 0.4925200045108795,
+ -0.6834070086479187, 0.6834070086479187, -0.2567310035228729,
+ -0.6835309863090515, 0.6835309863090515, 0.25606799125671387,
+ -0.06492599844932556, 0.06492500007152557, 0.9957759976387024,
+ 0.48139700293540955, -0.48139700293540955, 0.7324709892272949,
+ 0.6148040294647217, -0.6148040294647217, 0.4939970076084137,
+ -0.3698819875717163, 0.8930140137672424, -0.2563450038433075,
+ -0.36910200119018555, 0.8934370279312134, 0.2559959888458252,
+ -0.03550700098276138, 0.0838790014386177, 0.9958429932594299,
+ 0.26043900847435, -0.6297230124473572, 0.7318609952926636,
+ 0.3325839936733246, -0.803725004196167, 0.4933690130710602,
+ -0.002848000032827258, 0.9661769866943359, -0.25786298513412476,
+ -0.001921999966725707, 0.9670090079307556, 0.2547360062599182,
+ -0.00026500000967644155, 0.09227199852466583, 0.9957339763641357,
+ 0.00002300000051036477, -0.6820600032806396, 0.7312960028648376,
+ 0, -0.8703010082244873, 0.4925200045108795,
+ -0.002848000032827258, 0.9661769866943359, -0.25786298513412476,
+ 0.37905800342559814, 0.852770984172821, -0.35929998755455017,
+ 0.37711000442504883, 0.9140909910202026, 0.14908500015735626,
+ -0.001921999966725707, 0.9670090079307556, 0.2547360062599182,
+ 0.0275030005723238, 0.12255500257015228, 0.9920809864997864,
+ -0.00026500000967644155, 0.09227199852466583, 0.9957339763641357,
+ -0.26100900769233704, -0.6353650093078613, 0.7267630100250244,
+ 0.00002300000051036477, -0.6820600032806396, 0.7312960028648376,
+ -0.33248499035835266, -0.8042709827423096, 0.4925459921360016,
+ 0, -0.8703010082244873, 0.4925200045108795,
+ 0.6635469794273376, 0.6252639889717102, -0.4107919931411743,
+ 0.712664008140564, 0.6976209878921509, 0.07372400164604187,
+ 0.09972699731588364, 0.12198299914598465, 0.98750901222229,
+ -0.4873189926147461, -0.4885669946670532, 0.7237560153007507,
+ -0.6152420043945312, -0.6154839992523193, 0.4926010072231293,
+ 0.8800280094146729, 0.3387089967727661, -0.3329069912433624,
+ 0.9172769784927368, 0.36149299144744873, 0.16711199283599854,
+ 0.11358699947595596, 0.04806999862194061, 0.9923650026321411,
+ -0.6341490149497986, -0.2618879973888397, 0.7275090217590332,
+ -0.8041260242462158, -0.33270499110221863, 0.49263399839401245,
+ 0.9666900038719177, -0.010453999973833561, -0.2557379901409149,
+ 0.967441976070404, -0.00810300000011921, 0.25296199321746826,
+ 0.0934389978647232, -0.0012799999676644802, 0.9956240057945251,
+ -0.6821659803390503, 0.0003429999924264848, 0.7311969995498657,
+ -0.8703219890594482, 0.00005400000009103678, 0.492482990026474,
+ 0.9666900038719177, -0.010453999973833561, -0.2557379901409149,
+ 0.8930140137672424, -0.3698819875717163, -0.2563450038433075,
+ 0.8934370279312134, -0.36910200119018555, 0.2559970021247864,
+ 0.967441976070404, -0.00810300000011921, 0.25296199321746826,
+ 0.0838799998164177, -0.03550700098276138, 0.9958429932594299,
+ 0.0934389978647232, -0.0012799999676644802, 0.9956240057945251,
+ -0.629721999168396, 0.2604379951953888, 0.7318620085716248,
+ -0.6821659803390503, 0.0003429999924264848, 0.7311969995498657,
+ -0.803725004196167, 0.3325839936733246, 0.4933690130710602,
+ -0.8703219890594482, 0.00005400000009103678, 0.492482990026474,
+ 0.6834070086479187, -0.6834070086479187, -0.2567310035228729,
+ 0.6835309863090515, -0.6835309863090515, 0.25606799125671387,
+ 0.06492599844932556, -0.06492500007152557, 0.9957759976387024,
+ -0.48139700293540955, 0.48139700293540955, 0.7324709892272949,
+ -0.6148040294647217, 0.6148040294647217, 0.4939970076084137,
+ 0.3698819875717163, -0.8930140137672424, -0.2563450038433075,
+ 0.36910200119018555, -0.8934370279312134, 0.2559959888458252,
+ 0.03550700098276138, -0.0838790014386177, 0.9958429932594299,
+ -0.26043900847435, 0.6297230124473572, 0.7318609952926636,
+ -0.3325839936733246, 0.803725004196167, 0.4933690130710602,
+ 0, -0.9667419791221619, -0.25575199723243713,
+ 0, -0.9668239951133728, 0.2554430067539215,
+ 0, -0.09205400198698044, 0.9957540035247803,
+ 0, 0.6820489764213562, 0.7313070297241211,
+ 0, 0.8703010082244873, 0.4925200045108795,
+ 0, -0.9667419791221619, -0.25575199723243713,
+ -0.3698819875717163, -0.8930140137672424, -0.2563450038433075,
+ -0.36910200119018555, -0.8934370279312134, 0.2559970021247864,
+ 0, -0.9668239951133728, 0.2554430067539215,
+ -0.03550700098276138, -0.0838799998164177, 0.9958429932594299,
+ 0, -0.09205400198698044, 0.9957540035247803,
+ 0.2604379951953888, 0.629721999168396, 0.7318620085716248,
+ 0, 0.6820489764213562, 0.7313070297241211,
+ 0.3325839936733246, 0.803725004196167, 0.4933690130710602,
+ 0, 0.8703010082244873, 0.4925200045108795,
+ -0.6834070086479187, -0.6834070086479187, -0.2567310035228729,
+ -0.6835309863090515, -0.6835309863090515, 0.25606799125671387,
+ -0.06492500007152557, -0.06492599844932556, 0.9957759976387024,
+ 0.48139700293540955, 0.48139700293540955, 0.7324709892272949,
+ 0.6148040294647217, 0.6148040294647217, 0.4939970076084137,
+ -0.8930140137672424, -0.3698819875717163, -0.2563450038433075,
+ -0.8934370279312134, -0.36910200119018555, 0.2559959888458252,
+ -0.0838790014386177, -0.03550700098276138, 0.9958429932594299,
+ 0.6297230124473572, 0.26043900847435, 0.7318609952926636,
+ 0.803725004196167, 0.3325839936733246, 0.4933690130710602,
+ -0.9667419791221619, 0, -0.25575199723243713,
+ -0.9668239951133728, 0, 0.2554430067539215,
+ -0.09205400198698044, 0, 0.9957540035247803,
+ 0.6820489764213562, 0, 0.7313070297241211,
+ 0.8703010082244873, 0, 0.4925200045108795,
+ 0.8703010082244873, 0, 0.4925200045108795,
+ 0.803725004196167, -0.3325839936733246, 0.4933690130710602,
+ 0.8454390168190002, -0.34983500838279724, 0.40354499220848083,
+ 0.9153209924697876, 0, 0.4027250111103058,
+ 0.8699960112571716, -0.36004599928855896, 0.33685898780822754,
+ 0.9418079853057861, 0, 0.33615100383758545,
+ 0.9041929841041565, -0.37428000569343567, 0.20579099655151367,
+ 0.9786900281906128, 0, 0.20534199476242065,
+ 0.9218789935112, -0.38175201416015625, -0.06636899709701538,
+ 0.9978039860725403, 0, -0.06623899936676025,
+ 0.6148040294647217, -0.6148040294647217, 0.4939970076084137,
+ 0.6468020081520081, -0.6468020081520081, 0.40409600734710693,
+ 0.6656550168991089, -0.6656550168991089, 0.3373520076274872,
+ 0.6919230222702026, -0.6919230222702026, 0.20611999928951263,
+ 0.7055429816246033, -0.7055429816246033, -0.06647899746894836,
+ 0.3325839936733246, -0.803725004196167, 0.4933690130710602,
+ 0.34983500838279724, -0.8454390168190002, 0.40354499220848083,
+ 0.36004701256752014, -0.8699960112571716, 0.33685800433158875,
+ 0.37428000569343567, -0.9041929841041565, 0.20579099655151367,
+ 0.38175201416015625, -0.9218789935112, -0.06636899709701538,
+ 0, -0.8703010082244873, 0.4925200045108795,
+ 0, -0.9153209924697876, 0.4027250111103058,
+ 0, -0.9418079853057861, 0.33615100383758545,
+ 0, -0.9786900281906128, 0.20534199476242065,
+ 0, -0.9978039860725403, -0.06623899936676025,
+ 0, -0.8703010082244873, 0.4925200045108795,
+ -0.33248499035835266, -0.8042709827423096, 0.4925459921360016,
+ -0.34983500838279724, -0.8454390168190002, 0.40354499220848083,
+ 0, -0.9153209924697876, 0.4027250111103058,
+ -0.36004599928855896, -0.8699960112571716, 0.33685898780822754,
+ 0, -0.9418079853057861, 0.33615100383758545,
+ -0.37428000569343567, -0.9041929841041565, 0.20579099655151367,
+ 0, -0.9786900281906128, 0.20534199476242065,
+ -0.38175201416015625, -0.9218789935112, -0.06636899709701538,
+ 0, -0.9978039860725403, -0.06623899936676025,
+ -0.6152420043945312, -0.6154839992523193, 0.4926010072231293,
+ -0.6468020081520081, -0.6468020081520081, 0.40409600734710693,
+ -0.6656550168991089, -0.6656550168991089, 0.3373520076274872,
+ -0.6919230222702026, -0.6919230222702026, 0.20611999928951263,
+ -0.7055429816246033, -0.7055429816246033, -0.06647899746894836,
+ -0.8041260242462158, -0.33270499110221863, 0.49263399839401245,
+ -0.8454390168190002, -0.34983500838279724, 0.40354499220848083,
+ -0.8699960112571716, -0.36004701256752014, 0.33685800433158875,
+ -0.9041929841041565, -0.37428000569343567, 0.20579099655151367,
+ -0.9218789935112, -0.38175201416015625, -0.06636899709701538,
+ -0.8703219890594482, 0.00005400000009103678, 0.492482990026474,
+ -0.9153209924697876, 0, 0.4027250111103058,
+ -0.9418079853057861, 0, 0.33615100383758545,
+ -0.9786900281906128, 0, 0.20534199476242065,
+ -0.9978039860725403, 0, -0.06623899936676025,
+ -0.8703219890594482, 0.00005400000009103678, 0.492482990026474,
+ -0.803725004196167, 0.3325839936733246, 0.4933690130710602,
+ -0.8454390168190002, 0.34983500838279724, 0.40354499220848083,
+ -0.9153209924697876, 0, 0.4027250111103058,
+ -0.8699960112571716, 0.36004599928855896, 0.33685898780822754,
+ -0.9418079853057861, 0, 0.33615100383758545,
+ -0.9041929841041565, 0.37428000569343567, 0.20579099655151367,
+ -0.9786900281906128, 0, 0.20534199476242065,
+ -0.9218789935112, 0.38175201416015625, -0.06636899709701538,
+ -0.9978039860725403, 0, -0.06623899936676025,
+ -0.6148040294647217, 0.6148040294647217, 0.4939970076084137,
+ -0.6468020081520081, 0.6468020081520081, 0.40409600734710693,
+ -0.6656550168991089, 0.6656550168991089, 0.3373520076274872,
+ -0.6919230222702026, 0.6919230222702026, 0.20611999928951263,
+ -0.7055429816246033, 0.7055429816246033, -0.06647899746894836,
+ -0.3325839936733246, 0.803725004196167, 0.4933690130710602,
+ -0.34983500838279724, 0.8454390168190002, 0.40354499220848083,
+ -0.36004701256752014, 0.8699960112571716, 0.33685800433158875,
+ -0.37428000569343567, 0.9041929841041565, 0.20579099655151367,
+ -0.38175201416015625, 0.9218789935112, -0.06636899709701538,
+ 0, 0.8703010082244873, 0.4925200045108795,
+ 0, 0.9153209924697876, 0.4027250111103058,
+ 0, 0.9418079853057861, 0.33615100383758545,
+ 0, 0.9786900281906128, 0.20534199476242065,
+ 0, 0.9978039860725403, -0.06623899936676025,
+ 0, 0.8703010082244873, 0.4925200045108795,
+ 0.3325839936733246, 0.803725004196167, 0.4933690130710602,
+ 0.34983500838279724, 0.8454390168190002, 0.40354499220848083,
+ 0, 0.9153209924697876, 0.4027250111103058,
+ 0.36004599928855896, 0.8699960112571716, 0.33685898780822754,
+ 0, 0.9418079853057861, 0.33615100383758545,
+ 0.37428000569343567, 0.9041929841041565, 0.20579099655151367,
+ 0, 0.9786900281906128, 0.20534199476242065,
+ 0.38175201416015625, 0.9218789935112, -0.06636899709701538,
+ 0, 0.9978039860725403, -0.06623899936676025,
+ 0.6148040294647217, 0.6148040294647217, 0.4939970076084137,
+ 0.6468020081520081, 0.6468020081520081, 0.40409600734710693,
+ 0.6656550168991089, 0.6656550168991089, 0.3373520076274872,
+ 0.6919230222702026, 0.6919230222702026, 0.20611999928951263,
+ 0.7055429816246033, 0.7055429816246033, -0.06647899746894836,
+ 0.803725004196167, 0.3325839936733246, 0.4933690130710602,
+ 0.8454390168190002, 0.34983500838279724, 0.40354499220848083,
+ 0.8699960112571716, 0.36004701256752014, 0.33685800433158875,
+ 0.9041929841041565, 0.37428000569343567, 0.20579099655151367,
+ 0.9218789935112, 0.38175201416015625, -0.06636899709701538,
+ 0.8703010082244873, 0, 0.4925200045108795,
+ 0.9153209924697876, 0, 0.4027250111103058,
+ 0.9418079853057861, 0, 0.33615100383758545,
+ 0.9786900281906128, 0, 0.20534199476242065,
+ 0.9978039860725403, 0, -0.06623899936676025,
+ 0.9978039860725403, 0, -0.06623899936676025,
+ 0.9218789935112, -0.38175201416015625, -0.06636899709701538,
+ 0.8314369916915894, -0.3441790044307709, -0.4361799955368042,
+ 0.9001820087432861, 0, -0.4355129897594452,
+ 0.6735119819641113, -0.2785939872264862, -0.6846650242805481,
+ 0.7296109795570374, 0, -0.6838629841804504,
+ 0.6403989791870117, -0.26487401127815247, -0.7209240198135376,
+ 0.6939510107040405, 0, -0.7200220227241516,
+ 0.7329490184783936, -0.303166002035141, -0.6089959740638733,
+ 0.7939500212669373, 0, -0.6079840064048767,
+ 0.7055429816246033, -0.7055429816246033, -0.06647899746894836,
+ 0.6360920071601868, -0.6360920071601868, -0.4367780089378357,
+ 0.5149649977684021, -0.5149649977684021, -0.6852890253067017,
+ 0.48965099453926086, -0.48965099453926086, -0.7214459776878357,
+ 0.5605549812316895, -0.5605549812316895, -0.6095539927482605,
+ 0.38175201416015625, -0.9218789935112, -0.06636899709701538,
+ 0.3441790044307709, -0.8314369916915894, -0.4361799955368042,
+ 0.2785939872264862, -0.6735119819641113, -0.6846650242805481,
+ 0.26487401127815247, -0.6403989791870117, -0.7209240198135376,
+ 0.303166002035141, -0.7329490184783936, -0.6089959740638733,
+ 0, -0.9978039860725403, -0.06623899936676025,
+ 0, -0.9001820087432861, -0.4355129897594452,
+ 0, -0.7296109795570374, -0.6838629841804504,
+ 0, -0.6939510107040405, -0.7200220227241516,
+ 0, -0.7939500212669373, -0.6079840064048767,
+ 0, -0.9978039860725403, -0.06623899936676025,
+ -0.38175201416015625, -0.9218789935112, -0.06636899709701538,
+ -0.3441790044307709, -0.8314369916915894, -0.4361799955368042,
+ 0, -0.9001820087432861, -0.4355129897594452,
+ -0.2785939872264862, -0.6735119819641113, -0.6846650242805481,
+ 0, -0.7296109795570374, -0.6838629841804504,
+ -0.26487401127815247, -0.6403989791870117, -0.7209240198135376,
+ 0, -0.6939510107040405, -0.7200220227241516,
+ -0.303166002035141, -0.7329490184783936, -0.6089959740638733,
+ 0, -0.7939500212669373, -0.6079840064048767,
+ -0.7055429816246033, -0.7055429816246033, -0.06647899746894836,
+ -0.6360920071601868, -0.6360920071601868, -0.4367780089378357,
+ -0.5149649977684021, -0.5149649977684021, -0.6852890253067017,
+ -0.48965099453926086, -0.48965099453926086, -0.7214459776878357,
+ -0.5605549812316895, -0.5605549812316895, -0.6095539927482605,
+ -0.9218789935112, -0.38175201416015625, -0.06636899709701538,
+ -0.8314369916915894, -0.3441790044307709, -0.4361799955368042,
+ -0.6735119819641113, -0.2785939872264862, -0.6846650242805481,
+ -0.6403989791870117, -0.26487401127815247, -0.7209240198135376,
+ -0.7329490184783936, -0.303166002035141, -0.6089959740638733,
+ -0.9978039860725403, 0, -0.06623899936676025,
+ -0.9001820087432861, 0, -0.4355129897594452,
+ -0.7296109795570374, 0, -0.6838629841804504,
+ -0.6939510107040405, 0, -0.7200220227241516,
+ -0.7939500212669373, 0, -0.6079840064048767,
+ -0.9978039860725403, 0, -0.06623899936676025,
+ -0.9218789935112, 0.38175201416015625, -0.06636899709701538,
+ -0.8314369916915894, 0.3441790044307709, -0.4361799955368042,
+ -0.9001820087432861, 0, -0.4355129897594452,
+ -0.6735119819641113, 0.2785939872264862, -0.6846650242805481,
+ -0.7296109795570374, 0, -0.6838629841804504,
+ -0.6403989791870117, 0.26487401127815247, -0.7209240198135376,
+ -0.6939510107040405, 0, -0.7200220227241516,
+ -0.7329490184783936, 0.303166002035141, -0.6089959740638733,
+ -0.7939500212669373, 0, -0.6079840064048767,
+ -0.7055429816246033, 0.7055429816246033, -0.06647899746894836,
+ -0.6360920071601868, 0.6360920071601868, -0.4367780089378357,
+ -0.5149649977684021, 0.5149649977684021, -0.6852890253067017,
+ -0.48965099453926086, 0.48965099453926086, -0.7214459776878357,
+ -0.5605549812316895, 0.5605549812316895, -0.6095539927482605,
+ -0.38175201416015625, 0.9218789935112, -0.06636899709701538,
+ -0.3441790044307709, 0.8314369916915894, -0.4361799955368042,
+ -0.2785939872264862, 0.6735119819641113, -0.6846650242805481,
+ -0.26487401127815247, 0.6403989791870117, -0.7209240198135376,
+ -0.303166002035141, 0.7329490184783936, -0.6089959740638733,
+ 0, 0.9978039860725403, -0.06623899936676025,
+ 0, 0.9001820087432861, -0.4355129897594452,
+ 0, 0.7296109795570374, -0.6838629841804504,
+ 0, 0.6939510107040405, -0.7200220227241516,
+ 0, 0.7939500212669373, -0.6079840064048767,
+ 0, 0.9978039860725403, -0.06623899936676025,
+ 0.38175201416015625, 0.9218789935112, -0.06636899709701538,
+ 0.3441790044307709, 0.8314369916915894, -0.4361799955368042,
+ 0, 0.9001820087432861, -0.4355129897594452,
+ 0.2785939872264862, 0.6735119819641113, -0.6846650242805481,
+ 0, 0.7296109795570374, -0.6838629841804504,
+ 0.26487401127815247, 0.6403989791870117, -0.7209240198135376,
+ 0, 0.6939510107040405, -0.7200220227241516,
+ 0.303166002035141, 0.7329490184783936, -0.6089959740638733,
+ 0, 0.7939500212669373, -0.6079840064048767,
+ 0.7055429816246033, 0.7055429816246033, -0.06647899746894836,
+ 0.6360920071601868, 0.6360920071601868, -0.4367780089378357,
+ 0.5149649977684021, 0.5149649977684021, -0.6852890253067017,
+ 0.48965099453926086, 0.48965099453926086, -0.7214459776878357,
+ 0.5605549812316895, 0.5605549812316895, -0.6095539927482605,
+ 0.9218789935112, 0.38175201416015625, -0.06636899709701538,
+ 0.8314369916915894, 0.3441790044307709, -0.4361799955368042,
+ 0.6735119819641113, 0.2785939872264862, -0.6846650242805481,
+ 0.6403989791870117, 0.26487401127815247, -0.7209240198135376,
+ 0.7329490184783936, 0.303166002035141, -0.6089959740638733,
+ 0.9978039860725403, 0, -0.06623899936676025,
+ 0.9001820087432861, 0, -0.4355129897594452,
+ 0.7296109795570374, 0, -0.6838629841804504,
+ 0.6939510107040405, 0, -0.7200220227241516,
+ 0.7939500212669373, 0, -0.6079840064048767,
+ 0.7939500212669373, 0, -0.6079840064048767,
+ 0.7329490184783936, -0.303166002035141, -0.6089959740638733,
+ 0.576229989528656, -0.23821599781513214, -0.7818009853363037,
+ 0.6238600015640259, 0, -0.7815359830856323,
+ 0.16362899541854858, -0.06752700358629227, -0.9842079877853394,
+ 0.17729100584983826, 0, -0.984158992767334,
+ 0.04542100057005882, -0.018735000863671303, -0.9987919926643372,
+ 0.04920699819922447, 0, -0.9987890124320984,
+ 0, 0, -1,
+ 0, 0, -1,
+ 0.5605549812316895, -0.5605549812316895, -0.6095539927482605,
+ 0.44041600823402405, -0.44041600823402405, -0.7823479771614075,
+ 0.12490200251340866, -0.12490200251340866, -0.9842759966850281,
+ 0.034662000834941864, -0.034662000834941864, -0.9987980127334595,
+ 0, 0, -1,
+ 0.303166002035141, -0.7329490184783936, -0.6089959740638733,
+ 0.23821599781513214, -0.576229989528656, -0.7818009853363037,
+ 0.06752700358629227, -0.16362899541854858, -0.9842079877853394,
+ 0.018735000863671303, -0.04542100057005882, -0.9987919926643372,
+ 0, 0, -1,
+ 0, -0.7939500212669373, -0.6079840064048767,
+ 0, -0.6238600015640259, -0.7815359830856323,
+ 0, -0.17729100584983826, -0.984158992767334,
+ 0, -0.04920699819922447, -0.9987890124320984,
+ 0, 0, -1,
+ 0, -0.7939500212669373, -0.6079840064048767,
+ -0.303166002035141, -0.7329490184783936, -0.6089959740638733,
+ -0.23821599781513214, -0.576229989528656, -0.7818009853363037,
+ 0, -0.6238600015640259, -0.7815359830856323,
+ -0.06752700358629227, -0.16362899541854858, -0.9842079877853394,
+ 0, -0.17729100584983826, -0.984158992767334,
+ -0.018735000863671303, -0.04542100057005882, -0.9987919926643372,
+ 0, -0.04920699819922447, -0.9987890124320984,
+ 0, 0, -1,
+ 0, 0, -1,
+ -0.5605549812316895, -0.5605549812316895, -0.6095539927482605,
+ -0.44041600823402405, -0.44041600823402405, -0.7823479771614075,
+ -0.12490200251340866, -0.12490200251340866, -0.9842759966850281,
+ -0.034662000834941864, -0.034662000834941864, -0.9987980127334595,
+ 0, 0, -1,
+ -0.7329490184783936, -0.303166002035141, -0.6089959740638733,
+ -0.576229989528656, -0.23821599781513214, -0.7818009853363037,
+ -0.16362899541854858, -0.06752700358629227, -0.9842079877853394,
+ -0.04542100057005882, -0.018735000863671303, -0.9987919926643372,
+ 0, 0, -1,
+ -0.7939500212669373, 0, -0.6079840064048767,
+ -0.6238600015640259, 0, -0.7815359830856323,
+ -0.17729100584983826, 0, -0.984158992767334,
+ -0.04920699819922447, 0, -0.9987890124320984,
+ 0, 0, -1,
+ -0.7939500212669373, 0, -0.6079840064048767,
+ -0.7329490184783936, 0.303166002035141, -0.6089959740638733,
+ -0.576229989528656, 0.23821599781513214, -0.7818009853363037,
+ -0.6238600015640259, 0, -0.7815359830856323,
+ -0.16362899541854858, 0.06752700358629227, -0.9842079877853394,
+ -0.17729100584983826, 0, -0.984158992767334,
+ -0.04542100057005882, 0.018735000863671303, -0.9987919926643372,
+ -0.04920699819922447, 0, -0.9987890124320984,
+ 0, 0, -1,
+ 0, 0, -1,
+ -0.5605549812316895, 0.5605549812316895, -0.6095539927482605,
+ -0.44041600823402405, 0.44041600823402405, -0.7823479771614075,
+ -0.12490200251340866, 0.12490200251340866, -0.9842759966850281,
+ -0.034662000834941864, 0.034662000834941864, -0.9987980127334595,
+ 0, 0, -1,
+ -0.303166002035141, 0.7329490184783936, -0.6089959740638733,
+ -0.23821599781513214, 0.576229989528656, -0.7818009853363037,
+ -0.06752700358629227, 0.16362899541854858, -0.9842079877853394,
+ -0.018735000863671303, 0.04542100057005882, -0.9987919926643372,
+ 0, 0, -1,
+ 0, 0.7939500212669373, -0.6079840064048767,
+ 0, 0.6238600015640259, -0.7815359830856323,
+ 0, 0.17729100584983826, -0.984158992767334,
+ 0, 0.04920699819922447, -0.9987890124320984,
+ 0, 0, -1,
+ 0, 0.7939500212669373, -0.6079840064048767,
+ 0.303166002035141, 0.7329490184783936, -0.6089959740638733,
+ 0.23821599781513214, 0.576229989528656, -0.7818009853363037,
+ 0, 0.6238600015640259, -0.7815359830856323,
+ 0.06752700358629227, 0.16362899541854858, -0.9842079877853394,
+ 0, 0.17729100584983826, -0.984158992767334,
+ 0.018735000863671303, 0.04542100057005882, -0.9987919926643372,
+ 0, 0.04920699819922447, -0.9987890124320984,
+ 0, 0, -1,
+ 0, 0, -1,
+ 0.5605549812316895, 0.5605549812316895, -0.6095539927482605,
+ 0.44041600823402405, 0.44041600823402405, -0.7823479771614075,
+ 0.12490200251340866, 0.12490200251340866, -0.9842759966850281,
+ 0.034662000834941864, 0.034662000834941864, -0.9987980127334595,
+ 0, 0, -1,
+ 0.7329490184783936, 0.303166002035141, -0.6089959740638733,
+ 0.576229989528656, 0.23821599781513214, -0.7818009853363037,
+ 0.16362899541854858, 0.06752700358629227, -0.9842079877853394,
+ 0.04542100057005882, 0.018735000863671303, -0.9987919926643372,
+ 0, 0, -1,
+ 0.7939500212669373, 0, -0.6079840064048767,
+ 0.6238600015640259, 0, -0.7815359830856323,
+ 0.17729100584983826, 0, -0.984158992767334,
+ 0.04920699819922447, 0, -0.9987890124320984,
+ 0, 0, -1,
+ 0.007784999907016754, 0.00021499999274965376, -0.999970018863678,
+ 0.007038000039756298, -0.5829259753227234, -0.8124949932098389,
+ 0.0361270010471344, -0.5456140041351318, -0.837257981300354,
+ 0.03913800045847893, 0.0009879999561235309, -0.9992330074310303,
+ 0.16184599697589874, -0.5630490183830261, -0.8104209899902344,
+ 0.17951199412345886, 0.0043680001981556416, -0.9837459921836853,
+ 0.4823650121688843, -0.6427459716796875, -0.5951480269432068,
+ 0.6122999787330627, 0.010459000244736671, -0.790556013584137,
+ 0.7387199997901917, -0.6641989946365356, -0.11459299921989441,
+ 0.9861519932746887, 0.006668999791145325, -0.16570700705051422,
+ -0.0019079999765381217, -0.9867690205574036, 0.1621209979057312,
+ 0.002761000068858266, -0.9998499751091003, 0.017105000093579292,
+ 0.010532000102102757, -0.9972469806671143, 0.07339800149202347,
+ -0.06604000180959702, -0.9893029928207397, 0.13006900250911713,
+ -0.09442699700593948, -0.9953929781913757, 0.016594000160694122,
+ -0.009201999753713608, -0.4902929961681366, 0.8715090155601501,
+ -0.04860600084066391, -0.5394579768180847, 0.8406090140342712,
+ -0.22329799830913544, -0.5527390241622925, 0.8028810024261475,
+ -0.5963649749755859, -0.5751349925994873, 0.5599709749221802,
+ -0.8033369779586792, -0.5916029810905457, 0.06823500245809555,
+ -0.01056000031530857, -0.00010299999848939478, 0.9999439716339111,
+ -0.05879800021648407, -0.0007089999853633344, 0.9982699751853943,
+ -0.28071001172065735, -0.0032679999712854624, 0.9597870111465454,
+ -0.7497230172157288, -0.004267000127583742, 0.6617379784584045,
+ -0.9973509907722473, -0.0020580000709742308, 0.07271400094032288,
+ -0.01056000031530857, -0.00010299999848939478, 0.9999439716339111,
+ -0.008791999891400337, 0.49032899737358093, 0.8714929819107056,
+ -0.04649300128221512, 0.5387560129165649, 0.8411779999732971,
+ -0.05879800021648407, -0.0007089999853633344, 0.9982699751853943,
+ -0.21790899336338043, 0.5491610169410706, 0.8068069815635681,
+ -0.28071001172065735, -0.0032679999712854624, 0.9597870111465454,
+ -0.5972909927368164, 0.5741199851036072, 0.560027003288269,
+ -0.7497230172157288, -0.004267000127583742, 0.6617379784584045,
+ -0.8040000200271606, 0.5912910103797913, 0.0629120022058487,
+ -0.9973509907722473, -0.0020580000709742308, 0.07271400094032288,
+ -0.0018050000071525574, 0.986840009689331, 0.16169099509716034,
+ 0.0020310000982135534, 0.999891996383667, 0.014553000219166279,
+ 0.009215000085532665, 0.9981520175933838, 0.060068998485803604,
+ -0.059335000813007355, 0.9917230010032654, 0.11386600136756897,
+ -0.08690100163221359, 0.9961410164833069, 0.01228999998420477,
+ 0.006417000200599432, 0.5830950140953064, -0.812379002571106,
+ 0.03378299996256828, 0.5453730225563049, -0.8375130295753479,
+ 0.1571130007505417, 0.562188982963562, -0.8119469881057739,
+ 0.4844059944152832, 0.6465290188789368, -0.5893650054931641,
+ 0.7388700246810913, 0.6661880016326904, -0.10131999850273132,
+ 0.007784999907016754, 0.00021499999274965376, -0.999970018863678,
+ 0.03913800045847893, 0.0009879999561235309, -0.9992330074310303,
+ 0.17951199412345886, 0.0043680001981556416, -0.9837459921836853,
+ 0.6122999787330627, 0.010459000244736671, -0.790556013584137,
+ 0.9861519932746887, 0.006668999791145325, -0.16570700705051422,
+ 0.9861519932746887, 0.006668999791145325, -0.16570700705051422,
+ 0.7387199997901917, -0.6641989946365356, -0.11459299921989441,
+ 0.7256090044975281, -0.6373609900474548, 0.25935098528862,
+ 0.94651198387146, 0.0033569999504834414, 0.3226499855518341,
+ 0.6459450125694275, -0.6077200174331665, 0.46198800206184387,
+ 0.8258299827575684, 0.007451999932527542, 0.5638700127601624,
+ 0.5316150188446045, -0.5586140155792236, 0.6366599798202515,
+ 0.6500110030174255, 0.006936000194400549, 0.759893000125885,
+ 0.4249640107154846, -0.5955389738082886, 0.6817179918289185,
+ 0.5324289798736572, 0.005243999883532524, 0.8464580178260803,
+ -0.09442699700593948, -0.9953929781913757, 0.016594000160694122,
+ -0.04956100136041641, -0.9985759854316711, -0.01975500024855137,
+ -0.03781700134277344, -0.998649001121521, -0.035624999552965164,
+ -0.0379129983484745, -0.9986140131950378, -0.03651199862360954,
+ -0.1688539981842041, -0.9395300149917603, -0.2979460060596466,
+ -0.8033369779586792, -0.5916029810905457, 0.06823500245809555,
+ -0.7423409819602966, -0.5995240211486816, -0.2991659939289093,
+ -0.6196020245552063, -0.5795029997825623, -0.5294060111045837,
+ -0.483707994222641, -0.5438370108604431, -0.6857600212097168,
+ -0.44529199600219727, -0.4131770133972168, -0.7943549752235413,
+ -0.9973509907722473, -0.0020580000709742308, 0.07271400094032288,
+ -0.9265130162239075, -0.0019950000569224358, -0.3762570023536682,
+ -0.7539200186729431, -0.004317000042647123, -0.6569520235061646,
+ -0.5662239789962769, -0.003461000043898821, -0.8242440223693848,
+ -0.4818040132522583, -0.0018500000005587935, -0.8762770295143127,
+ -0.9973509907722473, -0.0020580000709742308, 0.07271400094032288,
+ -0.8040000200271606, 0.5912910103797913, 0.0629120022058487,
+ -0.7446749806404114, 0.5989770293235779, -0.29442399740219116,
+ -0.9265130162239075, -0.0019950000569224358, -0.3762570023536682,
+ -0.6219490170478821, 0.5781649947166443, -0.5281140208244324,
+ -0.7539200186729431, -0.004317000042647123, -0.6569520235061646,
+ -0.48117101192474365, 0.5428280234336853, -0.6883400082588196,
+ -0.5662239789962769, -0.003461000043898821, -0.8242440223693848,
+ -0.43805500864982605, 0.41574400663375854, -0.7970349788665771,
+ -0.4818040132522583, -0.0018500000005587935, -0.8762770295143127,
+ -0.08690100163221359, 0.9961410164833069, 0.01228999998420477,
+ -0.04433799907565117, 0.9988710284233093, -0.017055999487638474,
+ -0.026177000254392624, 0.9992600083351135, -0.02816700004041195,
+ -0.025293000042438507, 0.9992780089378357, -0.028332000598311424,
+ -0.15748199820518494, 0.9441670179367065, -0.28939300775527954,
+ 0.7388700246810913, 0.6661880016326904, -0.10131999850273132,
+ 0.7282440066337585, 0.63714200258255, 0.25240999460220337,
+ 0.6470540165901184, 0.6082550287246704, 0.4597249925136566,
+ 0.5229939818382263, 0.5621700286865234, 0.6406570076942444,
+ 0.4099780023097992, 0.6046689748764038, 0.6828569769859314,
+ 0.9861519932746887, 0.006668999791145325, -0.16570700705051422,
+ 0.94651198387146, 0.0033569999504834414, 0.3226499855518341,
+ 0.8258299827575684, 0.007451999932527542, 0.5638700127601624,
+ 0.6500110030174255, 0.006936000194400549, 0.759893000125885,
+ 0.5324289798736572, 0.005243999883532524, 0.8464580178260803,
+ -0.230786994099617, 0.006523000076413155, 0.9729819893836975,
+ -0.15287800133228302, -0.7101899981498718, 0.6872109770774841,
+ -0.31672099232673645, -0.7021129727363586, 0.6377500295639038,
+ -0.5489360094070435, 0.0015109999803826213, 0.8358629941940308,
+ -0.6010670065879822, -0.645330011844635, 0.471451997756958,
+ -0.8756710290908813, -0.009891999885439873, 0.4828070104122162,
+ -0.635890007019043, -0.629800021648407, 0.4460900127887726,
+ -0.8775539994239807, -0.01909100078046322, 0.47909700870513916,
+ -0.4357450008392334, -0.670009970664978, 0.6010090112686157,
+ -0.6961889863014221, -0.02449600026011467, 0.7174400091171265,
+ 0.11111299693584442, -0.9901599884033203, -0.08506900072097778,
+ 0.22330999374389648, -0.9747260212898254, 0.006539999973028898,
+ 0.19009700417518616, -0.9694579839706421, 0.15496399998664856,
+ 0.005270000081509352, -0.9818699955940247, 0.18948200345039368,
+ -0.011750999838113785, -0.9690240025520325, 0.24668699502944946,
+ 0.3439059853553772, -0.5994120240211487, -0.7227950096130371,
+ 0.5724899768829346, -0.5916270017623901, -0.5676559805870056,
+ 0.7874360084533691, -0.5605109930038452, -0.2564600110054016,
+ 0.6470969915390015, -0.6981409788131714, -0.3063740134239197,
+ 0.4275279939174652, -0.7535750269889832, -0.49934399127960205,
+ 0.4109260141849518, -0.0012839999981224537, -0.9116680026054382,
+ 0.6715199947357178, 0.0008989999769255519, -0.7409859895706177,
+ 0.9220259785652161, 0.00725199980661273, -0.3870599865913391,
+ 0.8469099998474121, 0.01385399978607893, -0.5315560102462769,
+ 0.5359240174293518, 0.010503999888896942, -0.8442010283470154,
+ 0.4109260141849518, -0.0012839999981224537, -0.9116680026054382,
+ 0.3411880135536194, 0.6009309887886047, -0.7228230237960815,
+ 0.5786640048027039, 0.591838002204895, -0.5611389875411987,
+ 0.6715199947357178, 0.0008989999769255519, -0.7409859895706177,
+ 0.7848690152168274, 0.5665420293807983, -0.25102001428604126,
+ 0.9220259785652161, 0.00725199980661273, -0.3870599865913391,
+ 0.6426810026168823, 0.7039899826049805, -0.3022570013999939,
+ 0.8469099998474121, 0.01385399978607893, -0.5315560102462769,
+ 0.4185889959335327, 0.7581170201301575, -0.5000420212745667,
+ 0.5359240174293518, 0.010503999888896942, -0.8442010283470154,
+ 0.11580599844455719, 0.9901139736175537, -0.07913900166749954,
+ 0.23281100392341614, 0.9724410176277161, 0.012564999982714653,
+ 0.20666299760341644, 0.9662799835205078, 0.15360000729560852,
+ 0.02449899911880493, 0.9865779876708984, 0.16144299507141113,
+ 0.0033809999004006386, 0.9774550199508667, 0.2111150026321411,
+ -0.13491199910640717, 0.7135509848594666, 0.6874909996986389,
+ -0.31953999400138855, 0.7050619721412659, 0.6330729722976685,
+ -0.6039019823074341, 0.6499029994010925, 0.4614419937133789,
+ -0.6318150162696838, 0.6400719881057739, 0.43716898560523987,
+ -0.4243049919605255, 0.6667500138282776, 0.6127070188522339,
+ -0.230786994099617, 0.006523000076413155, 0.9729819893836975,
+ -0.5489360094070435, 0.0015109999803826213, 0.8358629941940308,
+ -0.8756710290908813, -0.009891999885439873, 0.4828070104122162,
+ -0.8775539994239807, -0.01909100078046322, 0.47909700870513916,
+ -0.6961889863014221, -0.02449600026011467, 0.7174400091171265,
+ -0.6961889863014221, -0.02449600026011467, 0.7174400091171265,
+ -0.4357450008392334, -0.670009970664978, 0.6010090112686157,
+ -0.25985801219940186, -0.5525479912757874, 0.7919380068778992,
+ -0.42579901218414307, -0.010804999619722366, 0.9047530293464661,
+ 0.009537000209093094, 0.021669000387191772, 0.9997199773788452,
+ 0.022041000425815582, -0.001623000018298626, 0.9997559785842896,
+ 0.4101540148258209, 0.8490809798240662, 0.3329179883003235,
+ 0.9995980262756348, -0.01155600044876337, 0.02587899938225746,
+ 0.5415220260620117, 0.6370009779930115, -0.5486199855804443,
+ 0.7095860242843628, -0.009670999832451344, -0.7045519948005676,
+ -0.011750999838113785, -0.9690240025520325, 0.24668699502944946,
+ 0.046310000121593475, -0.8891720175743103, 0.45522499084472656,
+ -0.010688000358641148, -0.14889900386333466, 0.9887949824333191,
+ -0.04437499865889549, 0.7291200160980225, 0.6829460263252258,
+ 0.12282499670982361, 0.9923850297927856, 0.009232000447809696,
+ 0.4275279939174652, -0.7535750269889832, -0.49934399127960205,
+ 0.48183900117874146, -0.857479989528656, -0.18044300377368927,
+ 0.45527198910713196, -0.49992498755455017, 0.7367510199546814,
+ -0.22054199874401093, 0.3582780063152313, 0.9071930050849915,
+ -0.23591899871826172, 0.7157959938049316, 0.6572499871253967,
+ 0.5359240174293518, 0.010503999888896942, -0.8442010283470154,
+ 0.7280910015106201, 0.015584999695420265, -0.6853029727935791,
+ 0.8887389898300171, 0.016679000109434128, 0.4581089913845062,
+ -0.26009801030158997, -0.0007999999797903001, 0.965582013130188,
+ -0.37161099910736084, 0.004416999872773886, 0.9283779859542847,
+ 0.5359240174293518, 0.010503999888896942, -0.8442010283470154,
+ 0.4185889959335327, 0.7581170201301575, -0.5000420212745667,
+ 0.4801650047302246, 0.8588529825210571, -0.17836299538612366,
+ 0.7280910015106201, 0.015584999695420265, -0.6853029727935791,
+ 0.4881030023097992, 0.49794700741767883, 0.7168020009994507,
+ 0.8887389898300171, 0.016679000109434128, 0.4581089913845062,
+ -0.2220049947500229, -0.36189401149749756, 0.9053990244865417,
+ -0.26009801030158997, -0.0007999999797903001, 0.965582013130188,
+ -0.23540399968624115, -0.7104769945144653, 0.6631799936294556,
+ -0.37161099910736084, 0.004416999872773886, 0.9283779859542847,
+ 0.0033809999004006386, 0.9774550199508667, 0.2111150026321411,
+ 0.058719001710414886, 0.8971999883651733, 0.437703013420105,
+ 0.0013249999610707164, 0.164000004529953, 0.9864590167999268,
+ -0.04418899863958359, -0.7303190231323242, 0.6816750168800354,
+ 0.13880200684070587, -0.9897300004959106, -0.034189000725746155,
+ -0.4243049919605255, 0.6667500138282776, 0.6127070188522339,
+ -0.25888898968696594, 0.5453789830207825, 0.7972059845924377,
+ 0.012268000282347202, -0.01928500086069107, 0.9997389912605286,
+ 0.3986299932003021, -0.8456630110740662, 0.3548929989337921,
+ 0.5375639796257019, -0.6107370257377625, -0.5813990235328674,
+ -0.6961889863014221, -0.02449600026011467, 0.7174400091171265,
+ -0.42579901218414307, -0.010804999619722366, 0.9047530293464661,
+ 0.022041000425815582, -0.001623000018298626, 0.9997559785842896,
+ 0.9995980262756348, -0.01155600044876337, 0.02587899938225746,
+ 0.7095860242843628, -0.009670999832451344, -0.7045519948005676,
+ 0, 0, 1,
+ 0, 0, 1,
+ 0.7626410126686096, -0.31482499837875366, 0.5650339722633362,
+ 0.8245400190353394, -0.00001700000029813964, 0.5658029913902283,
+ 0.8479819893836975, -0.3500339984893799, -0.39799800515174866,
+ 0.917701005935669, -0.00003300000025774352, -0.397271990776062,
+ 0.8641409873962402, -0.35644200444221497, -0.3552600145339966,
+ 0.9352689981460571, -0.00011200000153621659, -0.3539389967918396,
+ 0.7209920287132263, -0.29793301224708557, 0.6256250143051147,
+ 0.7807120084762573, -0.00007500000356230885, 0.6248909831047058,
+ 0, 0, 1,
+ 0.5833569765090942, -0.5833380222320557, 0.5651649832725525,
+ 0.648485004901886, -0.6484479904174805, -0.3987259864807129,
+ 0.6608719825744629, -0.6607480049133301, -0.35589399933815,
+ 0.5518630146980286, -0.5517799854278564, 0.6252880096435547,
+ 0, 0, 1,
+ 0.31482499837875366, -0.762628972530365, 0.5650510191917419,
+ 0.35004499554634094, -0.8479880094528198, -0.39797601103782654,
+ 0.35647401213645935, -0.8641520142555237, -0.35519900918006897,
+ 0.29798200726509094, -0.7210670113563538, 0.6255149841308594,
+ 0, 0, 1,
+ -0.00001700000029813964, -0.8245400190353394, 0.5658029913902283,
+ -0.00003300000025774352, -0.917701005935669, -0.397271990776062,
+ -0.00011200000153621659, -0.9352689981460571, -0.3539389967918396,
+ -0.00007500000356230885, -0.7807120084762573, 0.6248900294303894,
+ 0, 0, 1,
+ 0, 0, 1,
+ -0.31482499837875366, -0.7626410126686096, 0.5650339722633362,
+ -0.00001700000029813964, -0.8245400190353394, 0.5658029913902283,
+ -0.3500339984893799, -0.8479819893836975, -0.39799800515174866,
+ -0.00003300000025774352, -0.917701005935669, -0.397271990776062,
+ -0.35644200444221497, -0.8641409873962402, -0.3552600145339966,
+ -0.00011200000153621659, -0.9352689981460571, -0.3539389967918396,
+ -0.29793301224708557, -0.7209920287132263, 0.6256250143051147,
+ -0.00007500000356230885, -0.7807120084762573, 0.6248900294303894,
+ 0, 0, 1,
+ -0.5833380222320557, -0.5833569765090942, 0.5651649832725525,
+ -0.6484479904174805, -0.648485004901886, -0.3987259864807129,
+ -0.6607480049133301, -0.6608719825744629, -0.35589399933815,
+ -0.5517799854278564, -0.5518630146980286, 0.6252880096435547,
+ 0, 0, 1,
+ -0.762628972530365, -0.31482499837875366, 0.5650510191917419,
+ -0.8479880094528198, -0.35004499554634094, -0.39797601103782654,
+ -0.8641520142555237, -0.35647401213645935, -0.35519900918006897,
+ -0.7210670113563538, -0.29798200726509094, 0.6255149841308594,
+ 0, 0, 1,
+ -0.8245400190353394, 0.00001700000029813964, 0.5658029913902283,
+ -0.917701005935669, 0.00003300000025774352, -0.397271990776062,
+ -0.9352689981460571, 0.00011200000153621659, -0.3539389967918396,
+ -0.7807120084762573, 0.00007500000356230885, 0.6248900294303894,
+ 0, 0, 1,
+ 0, 0, 1,
+ -0.7626410126686096, 0.31482499837875366, 0.5650339722633362,
+ -0.8245400190353394, 0.00001700000029813964, 0.5658029913902283,
+ -0.8479819893836975, 0.3500339984893799, -0.39799800515174866,
+ -0.917701005935669, 0.00003300000025774352, -0.397271990776062,
+ -0.8641409873962402, 0.35644200444221497, -0.3552600145339966,
+ -0.9352689981460571, 0.00011200000153621659, -0.3539389967918396,
+ -0.7209920287132263, 0.29793301224708557, 0.6256250143051147,
+ -0.7807120084762573, 0.00007500000356230885, 0.6248900294303894,
+ 0, 0, 1,
+ -0.5833569765090942, 0.5833380222320557, 0.5651649832725525,
+ -0.648485004901886, 0.6484479904174805, -0.3987259864807129,
+ -0.6608719825744629, 0.6607480049133301, -0.35589399933815,
+ -0.5518630146980286, 0.5517799854278564, 0.6252880096435547,
+ 0, 0, 1,
+ -0.31482499837875366, 0.762628972530365, 0.5650510191917419,
+ -0.35004499554634094, 0.8479880094528198, -0.39797601103782654,
+ -0.35647401213645935, 0.8641520142555237, -0.35519900918006897,
+ -0.29798200726509094, 0.7210670113563538, 0.6255149841308594,
+ 0, 0, 1,
+ 0.00001700000029813964, 0.8245400190353394, 0.5658029913902283,
+ 0.00003300000025774352, 0.917701005935669, -0.397271990776062,
+ 0.00011200000153621659, 0.9352689981460571, -0.3539389967918396,
+ 0.00007500000356230885, 0.7807120084762573, 0.6248900294303894,
+ 0, 0, 1,
+ 0, 0, 1,
+ 0.31482499837875366, 0.7626410126686096, 0.5650339722633362,
+ 0.00001700000029813964, 0.8245400190353394, 0.5658029913902283,
+ 0.3500339984893799, 0.8479819893836975, -0.39799800515174866,
+ 0.00003300000025774352, 0.917701005935669, -0.397271990776062,
+ 0.35644200444221497, 0.8641409873962402, -0.3552600145339966,
+ 0.00011200000153621659, 0.9352689981460571, -0.3539389967918396,
+ 0.29793301224708557, 0.7209920287132263, 0.6256250143051147,
+ 0.00007500000356230885, 0.7807120084762573, 0.6248900294303894,
+ 0, 0, 1,
+ 0.5833380222320557, 0.5833569765090942, 0.5651649832725525,
+ 0.6484479904174805, 0.648485004901886, -0.3987259864807129,
+ 0.6607480049133301, 0.6608719825744629, -0.35589399933815,
+ 0.5517799854278564, 0.5518630146980286, 0.6252880096435547,
+ 0, 0, 1,
+ 0.762628972530365, 0.31482499837875366, 0.5650510191917419,
+ 0.8479880094528198, 0.35004499554634094, -0.39797601103782654,
+ 0.8641520142555237, 0.35647401213645935, -0.35519900918006897,
+ 0.7210670113563538, 0.29798200726509094, 0.6255149841308594,
+ 0, 0, 1,
+ 0.8245400190353394, -0.00001700000029813964, 0.5658029913902283,
+ 0.917701005935669, -0.00003300000025774352, -0.397271990776062,
+ 0.9352689981460571, -0.00011200000153621659, -0.3539389967918396,
+ 0.7807120084762573, -0.00007500000356230885, 0.6248909831047058,
+ 0.7807120084762573, -0.00007500000356230885, 0.6248909831047058,
+ 0.7209920287132263, -0.29793301224708557, 0.6256250143051147,
+ 0.21797800064086914, -0.0902160033583641, 0.9717749953269958,
+ 0.23658299446105957, 0, 0.9716110229492188,
+ 0.1595889925956726, -0.06596100330352783, 0.9849770069122314,
+ 0.17308400571346283, 0, 0.9849069714546204,
+ 0.3504979908466339, -0.1447400003671646, 0.9253119826316833,
+ 0.37970298528671265, 0, 0.925108015537262,
+ 0.48558899760246277, -0.20147399604320526, 0.8506529927253723,
+ 0.5266720056533813, 0, 0.8500679731369019,
+ 0.5518630146980286, -0.5517799854278564, 0.6252880096435547,
+ 0.16663099825382233, -0.16663099825382233, 0.9718379974365234,
+ 0.12190800160169601, -0.12190800160169601, 0.9850260019302368,
+ 0.2676680088043213, -0.2676680088043213, 0.9255849719047546,
+ 0.37131500244140625, -0.37131500244140625, 0.8510289788246155,
+ 0.29798200726509094, -0.7210670113563538, 0.6255149841308594,
+ 0.0902160033583641, -0.21797800064086914, 0.9717749953269958,
+ 0.06596100330352783, -0.1595889925956726, 0.9849770069122314,
+ 0.1447400003671646, -0.3504979908466339, 0.9253119826316833,
+ 0.20147399604320526, -0.48558899760246277, 0.8506529927253723,
+ -0.00007500000356230885, -0.7807120084762573, 0.6248900294303894,
+ 0, -0.23658299446105957, 0.9716110229492188,
+ 0, -0.17308400571346283, 0.9849069714546204,
+ 0, -0.37970298528671265, 0.925108015537262,
+ 0, -0.5266720056533813, 0.8500679731369019,
+ -0.00007500000356230885, -0.7807120084762573, 0.6248900294303894,
+ -0.29793301224708557, -0.7209920287132263, 0.6256250143051147,
+ -0.0902160033583641, -0.21797800064086914, 0.9717749953269958,
+ 0, -0.23658299446105957, 0.9716110229492188,
+ -0.06596100330352783, -0.1595889925956726, 0.9849770069122314,
+ 0, -0.17308400571346283, 0.9849069714546204,
+ -0.1447400003671646, -0.3504979908466339, 0.9253119826316833,
+ 0, -0.37970298528671265, 0.925108015537262,
+ -0.20147399604320526, -0.48558899760246277, 0.8506529927253723,
+ 0, -0.5266720056533813, 0.8500679731369019,
+ -0.5517799854278564, -0.5518630146980286, 0.6252880096435547,
+ -0.16663099825382233, -0.16663099825382233, 0.9718379974365234,
+ -0.12190800160169601, -0.12190800160169601, 0.9850260019302368,
+ -0.2676680088043213, -0.2676680088043213, 0.9255849719047546,
+ -0.37131500244140625, -0.37131500244140625, 0.8510289788246155,
+ -0.7210670113563538, -0.29798200726509094, 0.6255149841308594,
+ -0.21797800064086914, -0.0902160033583641, 0.9717749953269958,
+ -0.1595889925956726, -0.06596100330352783, 0.9849770069122314,
+ -0.3504979908466339, -0.1447400003671646, 0.9253119826316833,
+ -0.48558899760246277, -0.20147399604320526, 0.8506529927253723,
+ -0.7807120084762573, 0.00007500000356230885, 0.6248900294303894,
+ -0.23658299446105957, 0, 0.9716110229492188,
+ -0.17308400571346283, 0, 0.9849069714546204,
+ -0.37970298528671265, 0, 0.925108015537262,
+ -0.5266720056533813, 0, 0.8500679731369019,
+ -0.7807120084762573, 0.00007500000356230885, 0.6248900294303894,
+ -0.7209920287132263, 0.29793301224708557, 0.6256250143051147,
+ -0.21797800064086914, 0.0902160033583641, 0.9717749953269958,
+ -0.23658299446105957, 0, 0.9716110229492188,
+ -0.1595889925956726, 0.06596100330352783, 0.9849770069122314,
+ -0.17308400571346283, 0, 0.9849069714546204,
+ -0.3504979908466339, 0.1447400003671646, 0.9253119826316833,
+ -0.37970298528671265, 0, 0.925108015537262,
+ -0.48558899760246277, 0.20147399604320526, 0.8506529927253723,
+ -0.5266720056533813, 0, 0.8500679731369019,
+ -0.5518630146980286, 0.5517799854278564, 0.6252880096435547,
+ -0.16663099825382233, 0.16663099825382233, 0.9718379974365234,
+ -0.12190800160169601, 0.12190800160169601, 0.9850260019302368,
+ -0.2676680088043213, 0.2676680088043213, 0.9255849719047546,
+ -0.37131500244140625, 0.37131500244140625, 0.8510289788246155,
+ -0.29798200726509094, 0.7210670113563538, 0.6255149841308594,
+ -0.0902160033583641, 0.21797800064086914, 0.9717749953269958,
+ -0.06596100330352783, 0.1595889925956726, 0.9849770069122314,
+ -0.1447400003671646, 0.3504979908466339, 0.9253119826316833,
+ -0.20147399604320526, 0.48558899760246277, 0.8506529927253723,
+ 0.00007500000356230885, 0.7807120084762573, 0.6248900294303894,
+ 0, 0.23658299446105957, 0.9716110229492188,
+ 0, 0.17308400571346283, 0.9849069714546204,
+ 0, 0.37970298528671265, 0.925108015537262,
+ 0, 0.5266720056533813, 0.8500679731369019,
+ 0.00007500000356230885, 0.7807120084762573, 0.6248900294303894,
+ 0.29793301224708557, 0.7209920287132263, 0.6256250143051147,
+ 0.0902160033583641, 0.21797800064086914, 0.9717749953269958,
+ 0, 0.23658299446105957, 0.9716110229492188,
+ 0.06596100330352783, 0.1595889925956726, 0.9849770069122314,
+ 0, 0.17308400571346283, 0.9849069714546204,
+ 0.1447400003671646, 0.3504979908466339, 0.9253119826316833,
+ 0, 0.37970298528671265, 0.925108015537262,
+ 0.20147399604320526, 0.48558899760246277, 0.8506529927253723,
+ 0, 0.5266720056533813, 0.8500679731369019,
+ 0.5517799854278564, 0.5518630146980286, 0.6252880096435547,
+ 0.16663099825382233, 0.16663099825382233, 0.9718379974365234,
+ 0.12190800160169601, 0.12190800160169601, 0.9850260019302368,
+ 0.2676680088043213, 0.2676680088043213, 0.9255849719047546,
+ 0.37131500244140625, 0.37131500244140625, 0.8510289788246155,
+ 0.7210670113563538, 0.29798200726509094, 0.6255149841308594,
+ 0.21797800064086914, 0.0902160033583641, 0.9717749953269958,
+ 0.1595889925956726, 0.06596100330352783, 0.9849770069122314,
+ 0.3504979908466339, 0.1447400003671646, 0.9253119826316833,
+ 0.48558899760246277, 0.20147399604320526, 0.8506529927253723,
+ 0.7807120084762573, -0.00007500000356230885, 0.6248909831047058,
+ 0.23658299446105957, 0, 0.9716110229492188,
+ 0.17308400571346283, 0, 0.9849069714546204,
+ 0.37970298528671265, 0, 0.925108015537262,
+ 0.5266720056533813, 0, 0.8500679731369019,
+};
+
+static const int teapot_indices[] = {
+ 0, 1, 2,
+ 2, 3, 0,
+ 3, 2, 4,
+ 4, 5, 3,
+ 5, 4, 6,
+ 6, 7, 5,
+ 7, 6, 8,
+ 8, 9, 7,
+ 1, 10, 11,
+ 11, 2, 1,
+ 2, 11, 12,
+ 12, 4, 2,
+ 4, 12, 13,
+ 13, 6, 4,
+ 6, 13, 14,
+ 14, 8, 6,
+ 10, 15, 16,
+ 16, 11, 10,
+ 11, 16, 17,
+ 17, 12, 11,
+ 12, 17, 18,
+ 18, 13, 12,
+ 13, 18, 19,
+ 19, 14, 13,
+ 15, 20, 21,
+ 21, 16, 15,
+ 16, 21, 22,
+ 22, 17, 16,
+ 17, 22, 23,
+ 23, 18, 17,
+ 18, 23, 24,
+ 24, 19, 18,
+ 25, 26, 27,
+ 27, 28, 25,
+ 28, 27, 29,
+ 29, 30, 28,
+ 30, 29, 31,
+ 31, 32, 30,
+ 32, 31, 33,
+ 33, 34, 32,
+ 26, 35, 36,
+ 36, 27, 26,
+ 27, 36, 37,
+ 37, 29, 27,
+ 29, 37, 38,
+ 38, 31, 29,
+ 31, 38, 39,
+ 39, 33, 31,
+ 35, 40, 41,
+ 41, 36, 35,
+ 36, 41, 42,
+ 42, 37, 36,
+ 37, 42, 43,
+ 43, 38, 37,
+ 38, 43, 44,
+ 44, 39, 38,
+ 40, 45, 46,
+ 46, 41, 40,
+ 41, 46, 47,
+ 47, 42, 41,
+ 42, 47, 48,
+ 48, 43, 42,
+ 43, 48, 49,
+ 49, 44, 43,
+ 50, 51, 52,
+ 52, 53, 50,
+ 53, 52, 54,
+ 54, 55, 53,
+ 55, 54, 56,
+ 56, 57, 55,
+ 57, 56, 58,
+ 58, 59, 57,
+ 51, 60, 61,
+ 61, 52, 51,
+ 52, 61, 62,
+ 62, 54, 52,
+ 54, 62, 63,
+ 63, 56, 54,
+ 56, 63, 64,
+ 64, 58, 56,
+ 60, 65, 66,
+ 66, 61, 60,
+ 61, 66, 67,
+ 67, 62, 61,
+ 62, 67, 68,
+ 68, 63, 62,
+ 63, 68, 69,
+ 69, 64, 63,
+ 65, 70, 71,
+ 71, 66, 65,
+ 66, 71, 72,
+ 72, 67, 66,
+ 67, 72, 73,
+ 73, 68, 67,
+ 68, 73, 74,
+ 74, 69, 68,
+ 75, 76, 77,
+ 77, 78, 75,
+ 78, 77, 79,
+ 79, 80, 78,
+ 80, 79, 81,
+ 81, 82, 80,
+ 82, 81, 83,
+ 83, 84, 82,
+ 76, 85, 86,
+ 86, 77, 76,
+ 77, 86, 87,
+ 87, 79, 77,
+ 79, 87, 88,
+ 88, 81, 79,
+ 81, 88, 89,
+ 89, 83, 81,
+ 85, 90, 91,
+ 91, 86, 85,
+ 86, 91, 92,
+ 92, 87, 86,
+ 87, 92, 93,
+ 93, 88, 87,
+ 88, 93, 94,
+ 94, 89, 88,
+ 90, 95, 96,
+ 96, 91, 90,
+ 91, 96, 97,
+ 97, 92, 91,
+ 92, 97, 98,
+ 98, 93, 92,
+ 93, 98, 99,
+ 99, 94, 93,
+ 100, 101, 102,
+ 102, 103, 100,
+ 103, 102, 104,
+ 104, 105, 103,
+ 105, 104, 106,
+ 106, 107, 105,
+ 107, 106, 108,
+ 108, 109, 107,
+ 101, 110, 111,
+ 111, 102, 101,
+ 102, 111, 112,
+ 112, 104, 102,
+ 104, 112, 113,
+ 113, 106, 104,
+ 106, 113, 114,
+ 114, 108, 106,
+ 110, 115, 116,
+ 116, 111, 110,
+ 111, 116, 117,
+ 117, 112, 111,
+ 112, 117, 118,
+ 118, 113, 112,
+ 113, 118, 119,
+ 119, 114, 113,
+ 115, 120, 121,
+ 121, 116, 115,
+ 116, 121, 122,
+ 122, 117, 116,
+ 117, 122, 123,
+ 123, 118, 117,
+ 118, 123, 124,
+ 124, 119, 118,
+ 125, 126, 127,
+ 127, 128, 125,
+ 128, 127, 129,
+ 129, 130, 128,
+ 130, 129, 131,
+ 131, 132, 130,
+ 132, 131, 133,
+ 133, 134, 132,
+ 126, 135, 136,
+ 136, 127, 126,
+ 127, 136, 137,
+ 137, 129, 127,
+ 129, 137, 138,
+ 138, 131, 129,
+ 131, 138, 139,
+ 139, 133, 131,
+ 135, 140, 141,
+ 141, 136, 135,
+ 136, 141, 142,
+ 142, 137, 136,
+ 137, 142, 143,
+ 143, 138, 137,
+ 138, 143, 144,
+ 144, 139, 138,
+ 140, 145, 146,
+ 146, 141, 140,
+ 141, 146, 147,
+ 147, 142, 141,
+ 142, 147, 148,
+ 148, 143, 142,
+ 143, 148, 149,
+ 149, 144, 143,
+ 150, 151, 152,
+ 152, 153, 150,
+ 153, 152, 154,
+ 154, 155, 153,
+ 155, 154, 156,
+ 156, 157, 155,
+ 157, 156, 158,
+ 158, 159, 157,
+ 151, 160, 161,
+ 161, 152, 151,
+ 152, 161, 162,
+ 162, 154, 152,
+ 154, 162, 163,
+ 163, 156, 154,
+ 156, 163, 164,
+ 164, 158, 156,
+ 160, 165, 166,
+ 166, 161, 160,
+ 161, 166, 167,
+ 167, 162, 161,
+ 162, 167, 168,
+ 168, 163, 162,
+ 163, 168, 169,
+ 169, 164, 163,
+ 165, 170, 171,
+ 171, 166, 165,
+ 166, 171, 172,
+ 172, 167, 166,
+ 167, 172, 173,
+ 173, 168, 167,
+ 168, 173, 174,
+ 174, 169, 168,
+ 175, 176, 177,
+ 177, 178, 175,
+ 178, 177, 179,
+ 179, 180, 178,
+ 180, 179, 181,
+ 181, 182, 180,
+ 182, 181, 183,
+ 183, 184, 182,
+ 176, 185, 186,
+ 186, 177, 176,
+ 177, 186, 187,
+ 187, 179, 177,
+ 179, 187, 188,
+ 188, 181, 179,
+ 181, 188, 189,
+ 189, 183, 181,
+ 185, 190, 191,
+ 191, 186, 185,
+ 186, 191, 192,
+ 192, 187, 186,
+ 187, 192, 193,
+ 193, 188, 187,
+ 188, 193, 194,
+ 194, 189, 188,
+ 190, 195, 196,
+ 196, 191, 190,
+ 191, 196, 197,
+ 197, 192, 191,
+ 192, 197, 198,
+ 198, 193, 192,
+ 193, 198, 199,
+ 199, 194, 193,
+ 200, 201, 202,
+ 202, 203, 200,
+ 203, 202, 204,
+ 204, 205, 203,
+ 205, 204, 206,
+ 206, 207, 205,
+ 207, 206, 208,
+ 208, 209, 207,
+ 201, 210, 211,
+ 211, 202, 201,
+ 202, 211, 212,
+ 212, 204, 202,
+ 204, 212, 213,
+ 213, 206, 204,
+ 206, 213, 214,
+ 214, 208, 206,
+ 210, 215, 216,
+ 216, 211, 210,
+ 211, 216, 217,
+ 217, 212, 211,
+ 212, 217, 218,
+ 218, 213, 212,
+ 213, 218, 219,
+ 219, 214, 213,
+ 215, 220, 221,
+ 221, 216, 215,
+ 216, 221, 222,
+ 222, 217, 216,
+ 217, 222, 223,
+ 223, 218, 217,
+ 218, 223, 224,
+ 224, 219, 218,
+ 225, 226, 227,
+ 227, 228, 225,
+ 228, 227, 229,
+ 229, 230, 228,
+ 230, 229, 231,
+ 231, 232, 230,
+ 232, 231, 233,
+ 233, 234, 232,
+ 226, 235, 236,
+ 236, 227, 226,
+ 227, 236, 237,
+ 237, 229, 227,
+ 229, 237, 238,
+ 238, 231, 229,
+ 231, 238, 239,
+ 239, 233, 231,
+ 235, 240, 241,
+ 241, 236, 235,
+ 236, 241, 242,
+ 242, 237, 236,
+ 237, 242, 243,
+ 243, 238, 237,
+ 238, 243, 244,
+ 244, 239, 238,
+ 240, 245, 246,
+ 246, 241, 240,
+ 241, 246, 247,
+ 247, 242, 241,
+ 242, 247, 248,
+ 248, 243, 242,
+ 243, 248, 249,
+ 249, 244, 243,
+ 250, 251, 252,
+ 252, 253, 250,
+ 253, 252, 254,
+ 254, 255, 253,
+ 255, 254, 256,
+ 256, 257, 255,
+ 257, 256, 258,
+ 258, 259, 257,
+ 251, 260, 261,
+ 261, 252, 251,
+ 252, 261, 262,
+ 262, 254, 252,
+ 254, 262, 263,
+ 263, 256, 254,
+ 256, 263, 264,
+ 264, 258, 256,
+ 260, 265, 266,
+ 266, 261, 260,
+ 261, 266, 267,
+ 267, 262, 261,
+ 262, 267, 268,
+ 268, 263, 262,
+ 263, 268, 269,
+ 269, 264, 263,
+ 265, 270, 271,
+ 271, 266, 265,
+ 266, 271, 272,
+ 272, 267, 266,
+ 267, 272, 273,
+ 273, 268, 267,
+ 268, 273, 274,
+ 274, 269, 268,
+ 275, 276, 277,
+ 277, 278, 275,
+ 278, 277, 279,
+ 279, 280, 278,
+ 280, 279, 281,
+ 281, 282, 280,
+ 282, 281, 283,
+ 283, 284, 282,
+ 276, 285, 286,
+ 286, 277, 276,
+ 277, 286, 287,
+ 287, 279, 277,
+ 279, 287, 288,
+ 288, 281, 279,
+ 281, 288, 289,
+ 289, 283, 281,
+ 285, 290, 291,
+ 291, 286, 285,
+ 286, 291, 292,
+ 292, 287, 286,
+ 287, 292, 293,
+ 293, 288, 287,
+ 288, 293, 294,
+ 294, 289, 288,
+ 290, 295, 296,
+ 296, 291, 290,
+ 291, 296, 297,
+ 297, 292, 291,
+ 292, 297, 298,
+ 298, 293, 292,
+ 293, 298, 299,
+ 299, 294, 293,
+ 300, 301, 302,
+ 302, 303, 300,
+ 303, 302, 304,
+ 304, 305, 303,
+ 305, 304, 306,
+ 306, 307, 305,
+ 307, 306, 308,
+ 308, 309, 307,
+ 301, 310, 311,
+ 311, 302, 301,
+ 302, 311, 312,
+ 312, 304, 302,
+ 304, 312, 313,
+ 313, 306, 304,
+ 306, 313, 314,
+ 314, 308, 306,
+ 310, 315, 316,
+ 316, 311, 310,
+ 311, 316, 317,
+ 317, 312, 311,
+ 312, 317, 318,
+ 318, 313, 312,
+ 313, 318, 319,
+ 319, 314, 313,
+ 315, 320, 321,
+ 321, 316, 315,
+ 316, 321, 322,
+ 322, 317, 316,
+ 317, 322, 323,
+ 323, 318, 317,
+ 318, 323, 324,
+ 324, 319, 318,
+ 325, 326, 327,
+ 327, 328, 325,
+ 328, 327, 329,
+ 329, 330, 328,
+ 330, 329, 331,
+ 331, 332, 330,
+ 332, 331, 333,
+ 333, 334, 332,
+ 326, 335, 336,
+ 336, 327, 326,
+ 327, 336, 337,
+ 337, 329, 327,
+ 329, 337, 338,
+ 338, 331, 329,
+ 331, 338, 339,
+ 339, 333, 331,
+ 335, 340, 341,
+ 341, 336, 335,
+ 336, 341, 342,
+ 342, 337, 336,
+ 337, 342, 343,
+ 343, 338, 337,
+ 338, 343, 344,
+ 344, 339, 338,
+ 340, 345, 346,
+ 346, 341, 340,
+ 341, 346, 347,
+ 347, 342, 341,
+ 342, 347, 348,
+ 348, 343, 342,
+ 343, 348, 349,
+ 349, 344, 343,
+ 350, 351, 352,
+ 352, 353, 350,
+ 353, 352, 354,
+ 354, 355, 353,
+ 355, 354, 356,
+ 356, 357, 355,
+ 357, 356, 358,
+ 358, 359, 357,
+ 351, 360, 361,
+ 361, 352, 351,
+ 352, 361, 362,
+ 362, 354, 352,
+ 354, 362, 363,
+ 363, 356, 354,
+ 356, 363, 364,
+ 364, 358, 356,
+ 360, 365, 366,
+ 366, 361, 360,
+ 361, 366, 367,
+ 367, 362, 361,
+ 362, 367, 368,
+ 368, 363, 362,
+ 363, 368, 369,
+ 369, 364, 363,
+ 365, 370, 371,
+ 371, 366, 365,
+ 366, 371, 372,
+ 372, 367, 366,
+ 367, 372, 373,
+ 373, 368, 367,
+ 368, 373, 374,
+ 374, 369, 368,
+ 375, 376, 377,
+ 377, 378, 375,
+ 378, 377, 379,
+ 379, 380, 378,
+ 380, 379, 381,
+ 381, 382, 380,
+ 382, 381, 383,
+ 383, 384, 382,
+ 376, 385, 386,
+ 386, 377, 376,
+ 377, 386, 387,
+ 387, 379, 377,
+ 379, 387, 388,
+ 388, 381, 379,
+ 381, 388, 389,
+ 389, 383, 381,
+ 385, 390, 391,
+ 391, 386, 385,
+ 386, 391, 392,
+ 392, 387, 386,
+ 387, 392, 393,
+ 393, 388, 387,
+ 388, 393, 394,
+ 394, 389, 388,
+ 390, 395, 396,
+ 396, 391, 390,
+ 391, 396, 397,
+ 397, 392, 391,
+ 392, 397, 398,
+ 398, 393, 392,
+ 393, 398, 399,
+ 399, 394, 393,
+ 400, 401, 402,
+ 402, 403, 400,
+ 403, 402, 404,
+ 404, 405, 403,
+ 405, 404, 406,
+ 406, 407, 405,
+ 407, 406, 408,
+ 408, 409, 407,
+ 401, 410, 411,
+ 411, 402, 401,
+ 402, 411, 412,
+ 412, 404, 402,
+ 404, 412, 413,
+ 413, 406, 404,
+ 406, 413, 414,
+ 414, 408, 406,
+ 410, 415, 416,
+ 416, 411, 410,
+ 411, 416, 417,
+ 417, 412, 411,
+ 412, 417, 418,
+ 418, 413, 412,
+ 413, 418, 419,
+ 419, 414, 413,
+ 415, 420, 421,
+ 421, 416, 415,
+ 416, 421, 422,
+ 422, 417, 416,
+ 417, 422, 423,
+ 423, 418, 417,
+ 418, 423, 424,
+ 424, 419, 418,
+ 425, 426, 427,
+ 427, 428, 425,
+ 428, 427, 429,
+ 429, 430, 428,
+ 430, 429, 431,
+ 431, 432, 430,
+ 432, 431, 433,
+ 433, 434, 432,
+ 426, 435, 436,
+ 436, 427, 426,
+ 427, 436, 437,
+ 437, 429, 427,
+ 429, 437, 438,
+ 438, 431, 429,
+ 431, 438, 439,
+ 439, 433, 431,
+ 435, 440, 441,
+ 441, 436, 435,
+ 436, 441, 442,
+ 442, 437, 436,
+ 437, 442, 443,
+ 443, 438, 437,
+ 438, 443, 444,
+ 444, 439, 438,
+ 440, 445, 446,
+ 446, 441, 440,
+ 441, 446, 447,
+ 447, 442, 441,
+ 442, 447, 448,
+ 448, 443, 442,
+ 443, 448, 449,
+ 449, 444, 443,
+ 450, 451, 452,
+ 452, 453, 450,
+ 453, 452, 454,
+ 454, 455, 453,
+ 455, 454, 456,
+ 456, 457, 455,
+ 457, 456, 458,
+ 458, 459, 457,
+ 451, 460, 461,
+ 461, 452, 451,
+ 452, 461, 462,
+ 462, 454, 452,
+ 454, 462, 463,
+ 463, 456, 454,
+ 456, 463, 464,
+ 464, 458, 456,
+ 460, 465, 466,
+ 466, 461, 460,
+ 461, 466, 467,
+ 467, 462, 461,
+ 462, 467, 468,
+ 468, 463, 462,
+ 463, 468, 469,
+ 469, 464, 463,
+ 465, 470, 471,
+ 471, 466, 465,
+ 466, 471, 472,
+ 472, 467, 466,
+ 467, 472, 473,
+ 473, 468, 467,
+ 468, 473, 474,
+ 474, 469, 468,
+ 475, 476, 477,
+ 477, 478, 475,
+ 478, 477, 479,
+ 479, 480, 478,
+ 480, 479, 481,
+ 481, 482, 480,
+ 482, 481, 483,
+ 483, 484, 482,
+ 476, 485, 486,
+ 486, 477, 476,
+ 477, 486, 487,
+ 487, 479, 477,
+ 479, 487, 488,
+ 488, 481, 479,
+ 481, 488, 489,
+ 489, 483, 481,
+ 485, 490, 491,
+ 491, 486, 485,
+ 486, 491, 492,
+ 492, 487, 486,
+ 487, 492, 493,
+ 493, 488, 487,
+ 488, 493, 494,
+ 494, 489, 488,
+ 490, 495, 496,
+ 496, 491, 490,
+ 491, 496, 497,
+ 497, 492, 491,
+ 492, 497, 498,
+ 498, 493, 492,
+ 493, 498, 499,
+ 499, 494, 493,
+ 500, 501, 502,
+ 502, 503, 500,
+ 503, 502, 504,
+ 504, 505, 503,
+ 505, 504, 506,
+ 506, 507, 505,
+ 507, 506, 508,
+ 508, 509, 507,
+ 501, 510, 511,
+ 511, 502, 501,
+ 502, 511, 512,
+ 512, 504, 502,
+ 504, 512, 513,
+ 513, 506, 504,
+ 506, 513, 514,
+ 514, 508, 506,
+ 510, 515, 516,
+ 516, 511, 510,
+ 511, 516, 517,
+ 517, 512, 511,
+ 512, 517, 518,
+ 518, 513, 512,
+ 513, 518, 519,
+ 519, 514, 513,
+ 515, 520, 521,
+ 521, 516, 515,
+ 516, 521, 522,
+ 522, 517, 516,
+ 517, 522, 523,
+ 523, 518, 517,
+ 518, 523, 524,
+ 524, 519, 518,
+ 525, 526, 527,
+ 527, 528, 525,
+ 528, 527, 529,
+ 529, 530, 528,
+ 530, 529, 531,
+ 531, 532, 530,
+ 532, 531, 533,
+ 533, 534, 532,
+ 526, 535, 536,
+ 536, 527, 526,
+ 527, 536, 537,
+ 537, 529, 527,
+ 529, 537, 538,
+ 538, 531, 529,
+ 531, 538, 539,
+ 539, 533, 531,
+ 535, 540, 541,
+ 541, 536, 535,
+ 536, 541, 542,
+ 542, 537, 536,
+ 537, 542, 543,
+ 543, 538, 537,
+ 538, 543, 544,
+ 544, 539, 538,
+ 540, 545, 546,
+ 546, 541, 540,
+ 541, 546, 547,
+ 547, 542, 541,
+ 542, 547, 548,
+ 548, 543, 542,
+ 543, 548, 549,
+ 549, 544, 543,
+ 550, 551, 552,
+ 552, 553, 550,
+ 553, 552, 554,
+ 554, 555, 553,
+ 555, 554, 556,
+ 556, 557, 555,
+ 557, 556, 558,
+ 558, 559, 557,
+ 551, 560, 561,
+ 561, 552, 551,
+ 552, 561, 562,
+ 562, 554, 552,
+ 554, 562, 563,
+ 563, 556, 554,
+ 556, 563, 564,
+ 564, 558, 556,
+ 560, 565, 566,
+ 566, 561, 560,
+ 561, 566, 567,
+ 567, 562, 561,
+ 562, 567, 568,
+ 568, 563, 562,
+ 563, 568, 569,
+ 569, 564, 563,
+ 565, 570, 571,
+ 571, 566, 565,
+ 566, 571, 572,
+ 572, 567, 566,
+ 567, 572, 573,
+ 573, 568, 567,
+ 568, 573, 574,
+ 574, 569, 568,
+ 575, 576, 577,
+ 577, 578, 575,
+ 578, 577, 579,
+ 579, 580, 578,
+ 580, 579, 581,
+ 581, 582, 580,
+ 582, 581, 583,
+ 583, 584, 582,
+ 576, 585, 586,
+ 586, 577, 576,
+ 577, 586, 587,
+ 587, 579, 577,
+ 579, 587, 588,
+ 588, 581, 579,
+ 581, 588, 589,
+ 589, 583, 581,
+ 585, 590, 591,
+ 591, 586, 585,
+ 586, 591, 592,
+ 592, 587, 586,
+ 587, 592, 593,
+ 593, 588, 587,
+ 588, 593, 594,
+ 594, 589, 588,
+ 590, 595, 596,
+ 596, 591, 590,
+ 591, 596, 597,
+ 597, 592, 591,
+ 592, 597, 598,
+ 598, 593, 592,
+ 593, 598, 599,
+ 599, 594, 593,
+ 600, 601, 602,
+ 602, 603, 600,
+ 603, 602, 604,
+ 604, 605, 603,
+ 605, 604, 606,
+ 606, 607, 605,
+ 607, 606, 608,
+ 608, 609, 607,
+ 601, 610, 611,
+ 611, 602, 601,
+ 602, 611, 612,
+ 612, 604, 602,
+ 604, 612, 613,
+ 613, 606, 604,
+ 606, 613, 614,
+ 614, 608, 606,
+ 610, 615, 616,
+ 616, 611, 610,
+ 611, 616, 617,
+ 617, 612, 611,
+ 612, 617, 618,
+ 618, 613, 612,
+ 613, 618, 619,
+ 619, 614, 613,
+ 615, 620, 621,
+ 621, 616, 615,
+ 616, 621, 622,
+ 622, 617, 616,
+ 617, 622, 623,
+ 623, 618, 617,
+ 618, 623, 624,
+ 624, 619, 618,
+ 625, 626, 627,
+ 627, 628, 625,
+ 628, 627, 629,
+ 629, 630, 628,
+ 630, 629, 631,
+ 631, 632, 630,
+ 632, 631, 633,
+ 633, 634, 632,
+ 626, 635, 636,
+ 636, 627, 626,
+ 627, 636, 637,
+ 637, 629, 627,
+ 629, 637, 638,
+ 638, 631, 629,
+ 631, 638, 639,
+ 639, 633, 631,
+ 635, 640, 641,
+ 641, 636, 635,
+ 636, 641, 642,
+ 642, 637, 636,
+ 637, 642, 643,
+ 643, 638, 637,
+ 638, 643, 644,
+ 644, 639, 638,
+ 640, 645, 646,
+ 646, 641, 640,
+ 641, 646, 647,
+ 647, 642, 641,
+ 642, 647, 648,
+ 648, 643, 642,
+ 643, 648, 649,
+ 649, 644, 643,
+ 650, 651, 652,
+ 652, 653, 650,
+ 653, 652, 654,
+ 654, 655, 653,
+ 655, 654, 656,
+ 656, 657, 655,
+ 657, 656, 658,
+ 658, 659, 657,
+ 651, 660, 661,
+ 661, 652, 651,
+ 652, 661, 662,
+ 662, 654, 652,
+ 654, 662, 663,
+ 663, 656, 654,
+ 656, 663, 664,
+ 664, 658, 656,
+ 660, 665, 666,
+ 666, 661, 660,
+ 661, 666, 667,
+ 667, 662, 661,
+ 662, 667, 668,
+ 668, 663, 662,
+ 663, 668, 669,
+ 669, 664, 663,
+ 665, 670, 671,
+ 671, 666, 665,
+ 666, 671, 672,
+ 672, 667, 666,
+ 667, 672, 673,
+ 673, 668, 667,
+ 668, 673, 674,
+ 674, 669, 668,
+ 675, 676, 677,
+ 677, 678, 675,
+ 678, 677, 679,
+ 679, 680, 678,
+ 680, 679, 681,
+ 681, 682, 680,
+ 682, 681, 683,
+ 683, 684, 682,
+ 676, 685, 686,
+ 686, 677, 676,
+ 677, 686, 687,
+ 687, 679, 677,
+ 679, 687, 688,
+ 688, 681, 679,
+ 681, 688, 689,
+ 689, 683, 681,
+ 685, 690, 691,
+ 691, 686, 685,
+ 686, 691, 692,
+ 692, 687, 686,
+ 687, 692, 693,
+ 693, 688, 687,
+ 688, 693, 694,
+ 694, 689, 688,
+ 690, 695, 696,
+ 696, 691, 690,
+ 691, 696, 697,
+ 697, 692, 691,
+ 692, 697, 698,
+ 698, 693, 692,
+ 693, 698, 699,
+ 699, 694, 693,
+ 700, 701, 702,
+ 702, 703, 700,
+ 703, 702, 704,
+ 704, 705, 703,
+ 705, 704, 706,
+ 706, 707, 705,
+ 707, 706, 708,
+ 708, 709, 707,
+ 701, 710, 711,
+ 711, 702, 701,
+ 702, 711, 712,
+ 712, 704, 702,
+ 704, 712, 713,
+ 713, 706, 704,
+ 706, 713, 714,
+ 714, 708, 706,
+ 710, 715, 716,
+ 716, 711, 710,
+ 711, 716, 717,
+ 717, 712, 711,
+ 712, 717, 718,
+ 718, 713, 712,
+ 713, 718, 719,
+ 719, 714, 713,
+ 715, 720, 721,
+ 721, 716, 715,
+ 716, 721, 722,
+ 722, 717, 716,
+ 717, 722, 723,
+ 723, 718, 717,
+ 718, 723, 724,
+ 724, 719, 718,
+ 725, 726, 727,
+ 727, 728, 725,
+ 728, 727, 729,
+ 729, 730, 728,
+ 730, 729, 731,
+ 731, 732, 730,
+ 732, 731, 733,
+ 733, 734, 732,
+ 726, 735, 736,
+ 736, 727, 726,
+ 727, 736, 737,
+ 737, 729, 727,
+ 729, 737, 738,
+ 738, 731, 729,
+ 731, 738, 739,
+ 739, 733, 731,
+ 735, 740, 741,
+ 741, 736, 735,
+ 736, 741, 742,
+ 742, 737, 736,
+ 737, 742, 743,
+ 743, 738, 737,
+ 738, 743, 744,
+ 744, 739, 738,
+ 740, 745, 746,
+ 746, 741, 740,
+ 741, 746, 747,
+ 747, 742, 741,
+ 742, 747, 748,
+ 748, 743, 742,
+ 743, 748, 749,
+ 749, 744, 743,
+ 750, 751, 752,
+ 752, 753, 750,
+ 753, 752, 754,
+ 754, 755, 753,
+ 755, 754, 756,
+ 756, 757, 755,
+ 757, 756, 758,
+ 758, 759, 757,
+ 751, 760, 761,
+ 761, 752, 751,
+ 752, 761, 762,
+ 762, 754, 752,
+ 754, 762, 763,
+ 763, 756, 754,
+ 756, 763, 764,
+ 764, 758, 756,
+ 760, 765, 766,
+ 766, 761, 760,
+ 761, 766, 767,
+ 767, 762, 761,
+ 762, 767, 768,
+ 768, 763, 762,
+ 763, 768, 769,
+ 769, 764, 763,
+ 765, 770, 771,
+ 771, 766, 765,
+ 766, 771, 772,
+ 772, 767, 766,
+ 767, 772, 773,
+ 773, 768, 767,
+ 768, 773, 774,
+ 774, 769, 768,
+ 775, 776, 777,
+ 777, 778, 775,
+ 778, 777, 779,
+ 779, 780, 778,
+ 780, 779, 781,
+ 781, 782, 780,
+ 782, 781, 783,
+ 783, 784, 782,
+ 776, 785, 786,
+ 786, 777, 776,
+ 777, 786, 787,
+ 787, 779, 777,
+ 779, 787, 788,
+ 788, 781, 779,
+ 781, 788, 789,
+ 789, 783, 781,
+ 785, 790, 791,
+ 791, 786, 785,
+ 786, 791, 792,
+ 792, 787, 786,
+ 787, 792, 793,
+ 793, 788, 787,
+ 788, 793, 794,
+ 794, 789, 788,
+ 790, 795, 796,
+ 796, 791, 790,
+ 791, 796, 797,
+ 797, 792, 791,
+ 792, 797, 798,
+ 798, 793, 792,
+ 793, 798, 799,
+ 799, 794, 793,
+};
diff --git a/demos/smoke/README.md b/demos/smoke/README.md
new file mode 100644
index 00000000..da0c7a9f
--- /dev/null
+++ b/demos/smoke/README.md
@@ -0,0 +1 @@
+This demo demonstrates multi-thread command buffer recording.
diff --git a/demos/smoke/Shell.cpp b/demos/smoke/Shell.cpp
new file mode 100644
index 00000000..e3fab496
--- /dev/null
+++ b/demos/smoke/Shell.cpp
@@ -0,0 +1,591 @@
+/*
+ * Copyright (C) 2016 Google, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <cassert>
+#include <array>
+#include <iostream>
+#include <string>
+#include <sstream>
+#include <set>
+#include "Helpers.h"
+#include "Shell.h"
+#include "Game.h"
+
+Shell::Shell(Game &game)
+ : game_(game), settings_(game.settings()), ctx_(),
+ game_tick_(1.0f / settings_.ticks_per_second), game_time_(game_tick_)
+{
+ // require generic WSI extensions
+ instance_extensions_.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
+ device_extensions_.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
+
+ // require "standard" validation layers
+ if (settings_.validate) {
+ device_layers_.push_back("VK_LAYER_LUNARG_standard_validation");
+ instance_layers_.push_back("VK_LAYER_LUNARG_standard_validation");
+
+ instance_extensions_.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
+ }
+}
+
+void Shell::log(LogPriority priority, const char *msg)
+{
+ std::ostream &st = (priority >= LOG_ERR) ? std::cerr : std::cout;
+ st << msg << "\n";
+}
+
+void Shell::init_vk()
+{
+ vk::init_dispatch_table_top(load_vk());
+
+ init_instance();
+ vk::init_dispatch_table_middle(ctx_.instance, false);
+
+ init_debug_report();
+ init_physical_dev();
+}
+
+void Shell::cleanup_vk()
+{
+ if (settings_.validate)
+ vk::DestroyDebugReportCallbackEXT(ctx_.instance, ctx_.debug_report, nullptr);
+
+ vk::DestroyInstance(ctx_.instance, nullptr);
+}
+
+bool Shell::debug_report_callback(VkDebugReportFlagsEXT flags,
+ VkDebugReportObjectTypeEXT obj_type,
+ uint64_t object,
+ size_t location,
+ int32_t msg_code,
+ const char *layer_prefix,
+ const char *msg)
+{
+ LogPriority prio = LOG_WARN;
+ if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT)
+ prio = LOG_ERR;
+ else if (flags & (VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT))
+ prio = LOG_WARN;
+ else if (flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT)
+ prio = LOG_INFO;
+ else if (flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT)
+ prio = LOG_DEBUG;
+
+ std::stringstream ss;
+ ss << layer_prefix << ": " << msg;
+
+ log(prio, ss.str().c_str());
+
+ return false;
+}
+
+void Shell::assert_all_instance_layers() const
+{
+ // enumerate instance layer
+ std::vector<VkLayerProperties> layers;
+ vk::enumerate(layers);
+
+ std::set<std::string> layer_names;
+ for (const auto &layer : layers)
+ layer_names.insert(layer.layerName);
+
+ // all listed instance layers are required
+ for (const auto &name : instance_layers_) {
+ if (layer_names.find(name) == layer_names.end()) {
+ std::stringstream ss;
+ ss << "instance layer " << name << " is missing";
+ throw std::runtime_error(ss.str());
+ }
+ }
+}
+
+void Shell::assert_all_instance_extensions() const
+{
+ // enumerate instance extensions
+ std::vector<VkExtensionProperties> exts;
+ vk::enumerate(nullptr, exts);
+
+ std::set<std::string> ext_names;
+ for (const auto &ext : exts)
+ ext_names.insert(ext.extensionName);
+
+ // all listed instance extensions are required
+ for (const auto &name : instance_extensions_) {
+ if (ext_names.find(name) == ext_names.end()) {
+ std::stringstream ss;
+ ss << "instance extension " << name << " is missing";
+ throw std::runtime_error(ss.str());
+ }
+ }
+}
+
+bool Shell::has_all_device_layers(VkPhysicalDevice phy) const
+{
+ // enumerate device layers
+ std::vector<VkLayerProperties> layers;
+ vk::enumerate(phy, layers);
+
+ std::set<std::string> layer_names;
+ for (const auto &layer : layers)
+ layer_names.insert(layer.layerName);
+
+ // all listed device layers are required
+ for (const auto &name : device_layers_) {
+ if (layer_names.find(name) == layer_names.end())
+ return false;
+ }
+
+ return true;
+}
+
+bool Shell::has_all_device_extensions(VkPhysicalDevice phy) const
+{
+ // enumerate device extensions
+ std::vector<VkExtensionProperties> exts;
+ vk::enumerate(phy, nullptr, exts);
+
+ std::set<std::string> ext_names;
+ for (const auto &ext : exts)
+ ext_names.insert(ext.extensionName);
+
+ // all listed device extensions are required
+ for (const auto &name : device_extensions_) {
+ if (ext_names.find(name) == ext_names.end())
+ return false;
+ }
+
+ return true;
+}
+
+void Shell::init_instance()
+{
+ assert_all_instance_layers();
+ assert_all_instance_extensions();
+
+ VkApplicationInfo app_info = {};
+ app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
+ app_info.pApplicationName = settings_.name.c_str();
+ app_info.applicationVersion = 0;
+ app_info.apiVersion = VK_MAKE_VERSION(1, 0, 0);
+
+ VkInstanceCreateInfo instance_info = {};
+ instance_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
+ instance_info.pApplicationInfo = &app_info;
+ instance_info.enabledLayerCount = static_cast<uint32_t>(instance_layers_.size());
+ instance_info.ppEnabledLayerNames = instance_layers_.data();
+ instance_info.enabledExtensionCount = static_cast<uint32_t>(instance_extensions_.size());
+ instance_info.ppEnabledExtensionNames = instance_extensions_.data();
+
+ vk::assert_success(vk::CreateInstance(&instance_info, nullptr, &ctx_.instance));
+}
+
+void Shell::init_debug_report()
+{
+ if (!settings_.validate)
+ return;
+
+ VkDebugReportCallbackCreateInfoEXT debug_report_info = {};
+ debug_report_info.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
+
+ debug_report_info.flags = VK_DEBUG_REPORT_WARNING_BIT_EXT |
+ VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT |
+ VK_DEBUG_REPORT_ERROR_BIT_EXT;
+ if (settings_.validate_verbose) {
+ debug_report_info.flags = VK_DEBUG_REPORT_INFORMATION_BIT_EXT |
+ VK_DEBUG_REPORT_DEBUG_BIT_EXT;
+ }
+
+ debug_report_info.pfnCallback = debug_report_callback;
+ debug_report_info.pUserData = reinterpret_cast<void *>(this);
+
+ vk::assert_success(vk::CreateDebugReportCallbackEXT(ctx_.instance,
+ &debug_report_info, nullptr, &ctx_.debug_report));
+}
+
+void Shell::init_physical_dev()
+{
+ // enumerate physical devices
+ std::vector<VkPhysicalDevice> phys;
+ vk::assert_success(vk::enumerate(ctx_.instance, phys));
+
+ ctx_.physical_dev = VK_NULL_HANDLE;
+ for (auto phy : phys) {
+ if (!has_all_device_layers(phy) || !has_all_device_extensions(phy))
+ continue;
+
+ // get queue properties
+ std::vector<VkQueueFamilyProperties> queues;
+ vk::get(phy, queues);
+
+ int game_queue_family = -1, present_queue_family = -1;
+ for (uint32_t i = 0; i < queues.size(); i++) {
+ const VkQueueFamilyProperties &q = queues[i];
+
+ // requires only GRAPHICS for game queues
+ const VkFlags game_queue_flags = VK_QUEUE_GRAPHICS_BIT;
+ if (game_queue_family < 0 &&
+ (q.queueFlags & game_queue_flags) == game_queue_flags)
+ game_queue_family = i;
+
+ // present queue must support the surface
+ if (present_queue_family < 0 && can_present(phy, i))
+ present_queue_family = i;
+
+ if (game_queue_family >= 0 && present_queue_family >= 0)
+ break;
+ }
+
+ if (game_queue_family >= 0 && present_queue_family >= 0) {
+ ctx_.physical_dev = phy;
+ ctx_.game_queue_family = game_queue_family;
+ ctx_.present_queue_family = present_queue_family;
+ break;
+ }
+ }
+
+ if (ctx_.physical_dev == VK_NULL_HANDLE)
+ throw std::runtime_error("failed to find any capable Vulkan physical device");
+}
+
+void Shell::create_context()
+{
+ create_dev();
+ vk::init_dispatch_table_bottom(ctx_.instance, ctx_.dev);
+
+ vk::GetDeviceQueue(ctx_.dev, ctx_.game_queue_family, 0, &ctx_.game_queue);
+ vk::GetDeviceQueue(ctx_.dev, ctx_.present_queue_family, 0, &ctx_.present_queue);
+
+ create_back_buffers();
+
+ // initialize ctx_.{surface,format} before attach_shell
+ create_swapchain();
+
+ game_.attach_shell(*this);
+}
+
+void Shell::destroy_context()
+{
+ if (ctx_.dev == VK_NULL_HANDLE)
+ return;
+
+ vk::DeviceWaitIdle(ctx_.dev);
+
+ destroy_swapchain();
+
+ game_.detach_shell();
+
+ destroy_back_buffers();
+
+ ctx_.game_queue = VK_NULL_HANDLE;
+ ctx_.present_queue = VK_NULL_HANDLE;
+
+ vk::DestroyDevice(ctx_.dev, nullptr);
+ ctx_.dev = VK_NULL_HANDLE;
+}
+
+void Shell::create_dev()
+{
+ VkDeviceCreateInfo dev_info = {};
+ dev_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
+
+ const std::vector<float> queue_priorities(settings_.queue_count, 0.0f);
+ std::array<VkDeviceQueueCreateInfo, 2> queue_info = {};
+ queue_info[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
+ queue_info[0].queueFamilyIndex = ctx_.game_queue_family;
+ queue_info[0].queueCount = settings_.queue_count;
+ queue_info[0].pQueuePriorities = queue_priorities.data();
+
+ if (ctx_.game_queue_family != ctx_.present_queue_family) {
+ queue_info[1].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
+ queue_info[1].queueFamilyIndex = ctx_.present_queue_family;
+ queue_info[1].queueCount = 1;
+ queue_info[1].pQueuePriorities = queue_priorities.data();
+
+ dev_info.queueCreateInfoCount = 2;
+ } else {
+ dev_info.queueCreateInfoCount = 1;
+ }
+
+ dev_info.pQueueCreateInfos = queue_info.data();
+
+ dev_info.enabledLayerCount = static_cast<uint32_t>(device_layers_.size());
+ dev_info.ppEnabledLayerNames = device_layers_.data();
+ dev_info.enabledExtensionCount = static_cast<uint32_t>(device_extensions_.size());
+ dev_info.ppEnabledExtensionNames = device_extensions_.data();
+
+ // disable all features
+ VkPhysicalDeviceFeatures features = {};
+ dev_info.pEnabledFeatures = &features;
+
+ vk::assert_success(vk::CreateDevice(ctx_.physical_dev, &dev_info, nullptr, &ctx_.dev));
+}
+
+void Shell::create_back_buffers()
+{
+ VkSemaphoreCreateInfo sem_info = {};
+ sem_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+
+ VkFenceCreateInfo fence_info = {};
+ fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
+ fence_info.flags = VK_FENCE_CREATE_SIGNALED_BIT;
+
+ // BackBuffer is used to track which swapchain image and its associated
+ // sync primitives are busy. Having more BackBuffer's than swapchain
+ // images may allows us to replace CPU wait on present_fence by GPU wait
+ // on acquire_semaphore.
+ const int count = settings_.back_buffer_count + 1;
+ for (int i = 0; i < count; i++) {
+ BackBuffer buf = {};
+ vk::assert_success(vk::CreateSemaphore(ctx_.dev, &sem_info, nullptr, &buf.acquire_semaphore));
+ vk::assert_success(vk::CreateSemaphore(ctx_.dev, &sem_info, nullptr, &buf.render_semaphore));
+ vk::assert_success(vk::CreateFence(ctx_.dev, &fence_info, nullptr, &buf.present_fence));
+
+ ctx_.back_buffers.push(buf);
+ }
+}
+
+void Shell::destroy_back_buffers()
+{
+ while (!ctx_.back_buffers.empty()) {
+ const auto &buf = ctx_.back_buffers.front();
+
+ vk::DestroySemaphore(ctx_.dev, buf.acquire_semaphore, nullptr);
+ vk::DestroySemaphore(ctx_.dev, buf.render_semaphore, nullptr);
+ vk::DestroyFence(ctx_.dev, buf.present_fence, nullptr);
+
+ ctx_.back_buffers.pop();
+ }
+}
+
+void Shell::create_swapchain()
+{
+ ctx_.surface = create_surface(ctx_.instance);
+
+ VkBool32 supported;
+ vk::assert_success(vk::GetPhysicalDeviceSurfaceSupportKHR(ctx_.physical_dev,
+ ctx_.present_queue_family, ctx_.surface, &supported));
+ // this should be guaranteed by the platform-specific can_present call
+ assert(supported);
+
+ std::vector<VkSurfaceFormatKHR> formats;
+ vk::get(ctx_.physical_dev, ctx_.surface, formats);
+ ctx_.format = formats[0];
+
+ // defer to resize_swapchain()
+ ctx_.swapchain = VK_NULL_HANDLE;
+ ctx_.extent.width = (uint32_t) -1;
+ ctx_.extent.height = (uint32_t) -1;
+}
+
+void Shell::destroy_swapchain()
+{
+ if (ctx_.swapchain != VK_NULL_HANDLE) {
+ game_.detach_swapchain();
+
+ vk::DestroySwapchainKHR(ctx_.dev, ctx_.swapchain, nullptr);
+ ctx_.swapchain = VK_NULL_HANDLE;
+ }
+
+ vk::DestroySurfaceKHR(ctx_.instance, ctx_.surface, nullptr);
+ ctx_.surface = VK_NULL_HANDLE;
+}
+
+void Shell::resize_swapchain(uint32_t width_hint, uint32_t height_hint)
+{
+ VkSurfaceCapabilitiesKHR caps;
+ vk::assert_success(vk::GetPhysicalDeviceSurfaceCapabilitiesKHR(ctx_.physical_dev,
+ ctx_.surface, &caps));
+
+ VkExtent2D extent = caps.currentExtent;
+ // use the hints
+ if (extent.width == (uint32_t) -1) {
+ extent.width = width_hint;
+ extent.height = height_hint;
+ }
+ // clamp width; to protect us from broken hints?
+ if (extent.width < caps.minImageExtent.width)
+ extent.width = caps.minImageExtent.width;
+ else if (extent.width > caps.maxImageExtent.width)
+ extent.width = caps.maxImageExtent.width;
+ // clamp height
+ if (extent.height < caps.minImageExtent.height)
+ extent.height = caps.minImageExtent.height;
+ else if (extent.height > caps.maxImageExtent.height)
+ extent.height = caps.maxImageExtent.height;
+
+ if (ctx_.extent.width == extent.width && ctx_.extent.height == extent.height)
+ return;
+
+ uint32_t image_count = settings_.back_buffer_count;
+ if (image_count < caps.minImageCount)
+ image_count = caps.minImageCount;
+ else if (image_count > caps.maxImageCount)
+ image_count = caps.maxImageCount;
+
+ assert(caps.supportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
+ assert(caps.supportedTransforms & caps.currentTransform);
+ assert(caps.supportedCompositeAlpha & (VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR |
+ VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR));
+ VkCompositeAlphaFlagBitsKHR composite_alpha =
+ (caps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR) ?
+ VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR : VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
+
+ std::vector<VkPresentModeKHR> modes;
+ vk::get(ctx_.physical_dev, ctx_.surface, modes);
+
+ // FIFO is the only mode universally supported
+ VkPresentModeKHR mode = VK_PRESENT_MODE_FIFO_KHR;
+ for (auto m : modes) {
+ if ((settings_.vsync && m == VK_PRESENT_MODE_MAILBOX_KHR) ||
+ (!settings_.vsync && m == VK_PRESENT_MODE_IMMEDIATE_KHR)) {
+ mode = m;
+ break;
+ }
+ }
+
+ VkSwapchainCreateInfoKHR swapchain_info = {};
+ swapchain_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
+ swapchain_info.surface = ctx_.surface;
+ swapchain_info.minImageCount = image_count;
+ swapchain_info.imageFormat = ctx_.format.format;
+ swapchain_info.imageColorSpace = ctx_.format.colorSpace;
+ swapchain_info.imageExtent = extent;
+ swapchain_info.imageArrayLayers = 1;
+ swapchain_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+
+ std::vector<uint32_t> queue_families(1, ctx_.game_queue_family);
+ if (ctx_.game_queue_family != ctx_.present_queue_family) {
+ queue_families.push_back(ctx_.present_queue_family);
+
+ swapchain_info.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
+ swapchain_info.queueFamilyIndexCount = (uint32_t)queue_families.size();
+ swapchain_info.pQueueFamilyIndices = queue_families.data();
+ } else {
+ swapchain_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ }
+
+ swapchain_info.preTransform = caps.currentTransform;;
+ swapchain_info.compositeAlpha = composite_alpha;
+ swapchain_info.presentMode = mode;
+ swapchain_info.clipped = true;
+ swapchain_info.oldSwapchain = ctx_.swapchain;
+
+ vk::assert_success(vk::CreateSwapchainKHR(ctx_.dev, &swapchain_info, nullptr, &ctx_.swapchain));
+ ctx_.extent = extent;
+
+ // destroy the old swapchain
+ if (swapchain_info.oldSwapchain != VK_NULL_HANDLE) {
+ game_.detach_swapchain();
+
+ vk::DeviceWaitIdle(ctx_.dev);
+ vk::DestroySwapchainKHR(ctx_.dev, swapchain_info.oldSwapchain, nullptr);
+ }
+
+ game_.attach_swapchain();
+}
+
+void Shell::add_game_time(float time)
+{
+ int max_ticks = 3;
+
+ if (!settings_.no_tick)
+ game_time_ += time;
+
+ while (game_time_ >= game_tick_ && max_ticks--) {
+ game_.on_tick();
+ game_time_ -= game_tick_;
+ }
+}
+
+void Shell::acquire_back_buffer()
+{
+ // acquire just once when not presenting
+ if (settings_.no_present &&
+ ctx_.acquired_back_buffer.acquire_semaphore != VK_NULL_HANDLE)
+ return;
+
+ auto &buf = ctx_.back_buffers.front();
+
+ // wait until acquire and render semaphores are waited/unsignaled
+ vk::assert_success(vk::WaitForFences(ctx_.dev, 1, &buf.present_fence,
+ true, UINT64_MAX));
+ // reset the fence
+ vk::assert_success(vk::ResetFences(ctx_.dev, 1, &buf.present_fence));
+
+ vk::assert_success(vk::AcquireNextImageKHR(ctx_.dev, ctx_.swapchain,
+ UINT64_MAX, buf.acquire_semaphore, VK_NULL_HANDLE,
+ &buf.image_index));
+
+ ctx_.acquired_back_buffer = buf;
+ ctx_.back_buffers.pop();
+}
+
+void Shell::present_back_buffer()
+{
+ const auto &buf = ctx_.acquired_back_buffer;
+
+ if (!settings_.no_render)
+ game_.on_frame(game_time_ / game_tick_);
+
+ if (settings_.no_present) {
+ fake_present();
+ return;
+ }
+
+ VkPresentInfoKHR present_info = {};
+ present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
+ present_info.waitSemaphoreCount = 1;
+ present_info.pWaitSemaphores = (settings_.no_render) ?
+ &buf.acquire_semaphore : &buf.render_semaphore;
+ present_info.swapchainCount = 1;
+ present_info.pSwapchains = &ctx_.swapchain;
+ present_info.pImageIndices = &buf.image_index;
+
+ vk::assert_success(vk::QueuePresentKHR(ctx_.present_queue, &present_info));
+
+ vk::assert_success(vk::QueueSubmit(ctx_.present_queue, 0, nullptr, buf.present_fence));
+ ctx_.back_buffers.push(buf);
+}
+
+void Shell::fake_present()
+{
+ const auto &buf = ctx_.acquired_back_buffer;
+
+ assert(settings_.no_present);
+
+ // wait render semaphore and signal acquire semaphore
+ if (!settings_.no_render) {
+ VkPipelineStageFlags stage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+ VkSubmitInfo submit_info = {};
+ submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ submit_info.waitSemaphoreCount = 1;
+ submit_info.pWaitSemaphores = &buf.render_semaphore;
+ submit_info.pWaitDstStageMask = &stage;
+ submit_info.signalSemaphoreCount = 1;
+ submit_info.pSignalSemaphores = &buf.acquire_semaphore;
+ vk::assert_success(vk::QueueSubmit(ctx_.game_queue, 1, &submit_info, VK_NULL_HANDLE));
+ }
+
+ // push the buffer back just once for Shell::cleanup_vk
+ if (buf.acquire_semaphore != ctx_.back_buffers.back().acquire_semaphore)
+ ctx_.back_buffers.push(buf);
+}
diff --git a/demos/smoke/Shell.h b/demos/smoke/Shell.h
new file mode 100644
index 00000000..2aa0b6f4
--- /dev/null
+++ b/demos/smoke/Shell.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2016 Google, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef SHELL_H
+#define SHELL_H
+
+#include <queue>
+#include <vector>
+#include <stdexcept>
+#include <vulkan/vulkan.h>
+
+#include "Game.h"
+
+class Game;
+
+class Shell {
+public:
+ Shell(const Shell &sh) = delete;
+ Shell &operator=(const Shell &sh) = delete;
+ virtual ~Shell() {}
+
+ struct BackBuffer {
+ uint32_t image_index;
+
+ VkSemaphore acquire_semaphore;
+ VkSemaphore render_semaphore;
+
+ // signaled when this struct is ready for reuse
+ VkFence present_fence;
+ };
+
+ struct Context {
+ VkInstance instance;
+ VkDebugReportCallbackEXT debug_report;
+
+ VkPhysicalDevice physical_dev;
+ uint32_t game_queue_family;
+ uint32_t present_queue_family;
+
+ VkDevice dev;
+ VkQueue game_queue;
+ VkQueue present_queue;
+
+ std::queue<BackBuffer> back_buffers;
+
+ VkSurfaceKHR surface;
+ VkSurfaceFormatKHR format;
+
+ VkSwapchainKHR swapchain;
+ VkExtent2D extent;
+
+ BackBuffer acquired_back_buffer;
+ };
+ const Context &context() const { return ctx_; }
+
+ enum LogPriority {
+ LOG_DEBUG,
+ LOG_INFO,
+ LOG_WARN,
+ LOG_ERR,
+ };
+ virtual void log(LogPriority priority, const char *msg);
+
+ virtual void run() = 0;
+ virtual void quit() = 0;
+
+protected:
+ Shell(Game &game);
+
+ void init_vk();
+ void cleanup_vk();
+
+ void create_context();
+ void destroy_context();
+
+ void resize_swapchain(uint32_t width_hint, uint32_t height_hint);
+
+ void add_game_time(float time);
+
+ void acquire_back_buffer();
+ void present_back_buffer();
+
+ Game &game_;
+ const Game::Settings &settings_;
+
+ std::vector<const char *> instance_layers_;
+ std::vector<const char *> instance_extensions_;
+
+ std::vector<const char *> device_layers_;
+ std::vector<const char *> device_extensions_;
+
+private:
+ bool debug_report_callback(VkDebugReportFlagsEXT flags,
+ VkDebugReportObjectTypeEXT obj_type,
+ uint64_t object,
+ size_t location,
+ int32_t msg_code,
+ const char *layer_prefix,
+ const char *msg);
+ static VKAPI_ATTR VkBool32 VKAPI_CALL debug_report_callback(
+ VkDebugReportFlagsEXT flags,
+ VkDebugReportObjectTypeEXT obj_type,
+ uint64_t object,
+ size_t location,
+ int32_t msg_code,
+ const char *layer_prefix,
+ const char *msg,
+ void *user_data)
+ {
+ Shell *shell = reinterpret_cast<Shell *>(user_data);
+ return shell->debug_report_callback(flags, obj_type, object, location, msg_code, layer_prefix, msg);
+ }
+
+ void assert_all_instance_layers() const;
+ void assert_all_instance_extensions() const;
+
+ bool has_all_device_layers(VkPhysicalDevice phy) const;
+ bool has_all_device_extensions(VkPhysicalDevice phy) const;
+
+ // called by init_vk
+ virtual PFN_vkGetInstanceProcAddr load_vk() = 0;
+ virtual bool can_present(VkPhysicalDevice phy, uint32_t queue_family) = 0;
+ void init_instance();
+ void init_debug_report();
+ void init_physical_dev();
+
+ // called by create_context
+ void create_dev();
+ void create_back_buffers();
+ void destroy_back_buffers();
+ virtual VkSurfaceKHR create_surface(VkInstance instance) = 0;
+ void create_swapchain();
+ void destroy_swapchain();
+
+ void fake_present();
+
+ Context ctx_;
+
+ const float game_tick_;
+ float game_time_;
+};
+
+#endif // SHELL_H
diff --git a/demos/smoke/ShellAndroid.cpp b/demos/smoke/ShellAndroid.cpp
new file mode 100644
index 00000000..4b813b46
--- /dev/null
+++ b/demos/smoke/ShellAndroid.cpp
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2016 Google, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <cassert>
+#include <dlfcn.h>
+#include <time.h>
+#include <android/log.h>
+
+#include "Helpers.h"
+#include "Game.h"
+#include "ShellAndroid.h"
+
+namespace {
+
+// copied from ShellXCB.cpp
+class PosixTimer {
+public:
+ PosixTimer()
+ {
+ reset();
+ }
+
+ void reset()
+ {
+ clock_gettime(CLOCK_MONOTONIC, &start_);
+ }
+
+ double get() const
+ {
+ struct timespec now;
+ clock_gettime(CLOCK_MONOTONIC, &now);
+
+ constexpr long one_s_in_ns = 1000 * 1000 * 1000;
+ constexpr double one_s_in_ns_d = static_cast<double>(one_s_in_ns);
+
+ time_t s = now.tv_sec - start_.tv_sec;
+ long ns;
+ if (now.tv_nsec > start_.tv_nsec) {
+ ns = now.tv_nsec - start_.tv_nsec;
+ } else {
+ assert(s > 0);
+ s--;
+ ns = one_s_in_ns - (start_.tv_nsec - now.tv_nsec);
+ }
+
+ return static_cast<double>(s) + static_cast<double>(ns) / one_s_in_ns_d;
+ }
+
+private:
+ struct timespec start_;
+};
+
+} // namespace
+
+ShellAndroid::ShellAndroid(android_app &app, Game &game) : Shell(game), app_(app)
+{
+ instance_extensions_.push_back(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME);
+
+ app_dummy();
+ app_.userData = this;
+ app_.onAppCmd = on_app_cmd;
+ app_.onInputEvent = on_input_event;
+
+ init_vk();
+}
+
+ShellAndroid::~ShellAndroid()
+{
+ cleanup_vk();
+ dlclose(lib_handle_);
+}
+
+void ShellAndroid::log(LogPriority priority, const char *msg)
+{
+ int prio;
+
+ switch (priority) {
+ case LOG_DEBUG:
+ prio = ANDROID_LOG_DEBUG;
+ break;
+ case LOG_INFO:
+ prio = ANDROID_LOG_INFO;
+ break;
+ case LOG_WARN:
+ prio = ANDROID_LOG_WARN;
+ break;
+ case LOG_ERR:
+ prio = ANDROID_LOG_ERROR;
+ break;
+ default:
+ prio = ANDROID_LOG_UNKNOWN;
+ break;
+ }
+
+ __android_log_write(prio, settings_.name.c_str(), msg);
+}
+
+PFN_vkGetInstanceProcAddr ShellAndroid::load_vk()
+{
+ const char filename[] = "libvulkan.so";
+ void *handle = nullptr, *symbol = nullptr;
+
+ handle = dlopen(filename, RTLD_LAZY);
+ if (handle)
+ symbol = dlsym(handle, "vkGetInstanceProcAddr");
+ if (!symbol) {
+ if (handle)
+ dlclose(handle);
+
+ throw std::runtime_error(dlerror());
+ }
+
+ lib_handle_ = handle;
+
+ return reinterpret_cast<PFN_vkGetInstanceProcAddr>(symbol);
+}
+
+VkSurfaceKHR ShellAndroid::create_surface(VkInstance instance)
+{
+ VkAndroidSurfaceCreateInfoKHR surface_info = {};
+ surface_info.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
+ surface_info.window = app_.window;
+
+ VkSurfaceKHR surface;
+ vk::assert_success(vk::CreateAndroidSurfaceKHR(instance, &surface_info, nullptr, &surface));
+
+ return surface;
+}
+
+void ShellAndroid::on_app_cmd(int32_t cmd)
+{
+ switch (cmd) {
+ case APP_CMD_INIT_WINDOW:
+ create_context();
+ resize_swapchain(0, 0);
+ break;
+ case APP_CMD_TERM_WINDOW:
+ destroy_context();
+ break;
+ case APP_CMD_WINDOW_RESIZED:
+ resize_swapchain(0, 0);
+ break;
+ case APP_CMD_STOP:
+ ANativeActivity_finish(app_.activity);
+ break;
+ default:
+ break;
+ }
+}
+
+int32_t ShellAndroid::on_input_event(const AInputEvent *event)
+{
+ if (AInputEvent_getType(event) != AINPUT_EVENT_TYPE_MOTION)
+ return false;
+
+ bool handled = false;
+
+ switch (AMotionEvent_getAction(event) & AMOTION_EVENT_ACTION_MASK) {
+ case AMOTION_EVENT_ACTION_UP:
+ game_.on_key(Game::KEY_SPACE);
+ handled = true;
+ break;
+ default:
+ break;
+ }
+
+ return handled;
+}
+
+void ShellAndroid::quit()
+{
+ ANativeActivity_finish(app_.activity);
+}
+
+void ShellAndroid::run()
+{
+ PosixTimer timer;
+
+ double current_time = timer.get();
+
+ while (true) {
+ struct android_poll_source *source;
+ while (true) {
+ int timeout = (settings_.animate && app_.window) ? 0 : -1;
+ if (ALooper_pollAll(timeout, nullptr, nullptr,
+ reinterpret_cast<void **>(&source)) < 0)
+ break;
+
+ if (source)
+ source->process(&app_, source);
+ }
+
+ if (app_.destroyRequested)
+ break;
+
+ if (!app_.window)
+ continue;
+
+ acquire_back_buffer();
+
+ double t = timer.get();
+ add_game_time(static_cast<float>(t - current_time));
+
+ present_back_buffer();
+
+ current_time = t;
+ }
+}
diff --git a/demos/smoke/ShellAndroid.h b/demos/smoke/ShellAndroid.h
new file mode 100644
index 00000000..dae3d072
--- /dev/null
+++ b/demos/smoke/ShellAndroid.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2016 Google, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef SHELL_ANDROID_H
+#define SHELL_ANDROID_H
+
+#include <android_native_app_glue.h>
+#include "Shell.h"
+
+class ShellAndroid : public Shell {
+public:
+ ShellAndroid(android_app &app, Game &game);
+ ~ShellAndroid();
+
+ void log(LogPriority priority, const char *msg);
+
+ void run();
+ void quit();
+
+private:
+ PFN_vkGetInstanceProcAddr load_vk();
+ bool can_present(VkPhysicalDevice phy, uint32_t queue_family) { return true; }
+
+ VkSurfaceKHR create_surface(VkInstance instance);
+
+ void on_app_cmd(int32_t cmd);
+ int32_t on_input_event(const AInputEvent *event);
+
+ static inline void on_app_cmd(android_app *app, int32_t cmd);
+ static inline int32_t on_input_event(android_app *app, AInputEvent *event);
+
+ android_app &app_;
+
+ void *lib_handle_;
+};
+
+void ShellAndroid::on_app_cmd(android_app *app, int32_t cmd)
+{
+ auto android = reinterpret_cast<ShellAndroid *>(app->userData);
+ android->on_app_cmd(cmd);
+}
+
+int32_t ShellAndroid::on_input_event(android_app *app, AInputEvent *event)
+{
+ auto android = reinterpret_cast<ShellAndroid *>(app->userData);
+ return android->on_input_event(event);
+}
+
+#endif // SHELL_ANDROID_H
diff --git a/demos/smoke/ShellWin32.cpp b/demos/smoke/ShellWin32.cpp
new file mode 100644
index 00000000..1a1a844c
--- /dev/null
+++ b/demos/smoke/ShellWin32.cpp
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2016 Google, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <cassert>
+#include <iostream>
+#include <sstream>
+
+#include "Helpers.h"
+#include "Game.h"
+#include "ShellWin32.h"
+
+namespace {
+
+class Win32Timer {
+public:
+ Win32Timer()
+ {
+ LARGE_INTEGER freq;
+ QueryPerformanceFrequency(&freq);
+ freq_ = static_cast<double>(freq.QuadPart);
+
+ reset();
+ }
+
+ void reset()
+ {
+ QueryPerformanceCounter(&start_);
+ }
+
+ double get() const
+ {
+ LARGE_INTEGER now;
+ QueryPerformanceCounter(&now);
+
+ return static_cast<double>(now.QuadPart - start_.QuadPart) / freq_;
+ }
+
+private:
+ double freq_;
+ LARGE_INTEGER start_;
+};
+
+} // namespace
+
+ShellWin32::ShellWin32(Game &game) : Shell(game), hwnd_(nullptr)
+{
+ instance_extensions_.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
+ init_vk();
+}
+
+ShellWin32::~ShellWin32()
+{
+ cleanup_vk();
+ FreeLibrary(hmodule_);
+}
+
+void ShellWin32::create_window()
+{
+ const std::string class_name(settings_.name + "WindowClass");
+
+ hinstance_ = GetModuleHandle(nullptr);
+
+ WNDCLASSEX win_class = {};
+ win_class.cbSize = sizeof(WNDCLASSEX);
+ win_class.style = CS_HREDRAW | CS_VREDRAW;
+ win_class.lpfnWndProc = window_proc;
+ win_class.hInstance = hinstance_;
+ win_class.hCursor = LoadCursor(nullptr, IDC_ARROW);
+ win_class.lpszClassName = class_name.c_str();
+ RegisterClassEx(&win_class);
+
+ const DWORD win_style =
+ WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE | WS_OVERLAPPEDWINDOW;
+
+ RECT win_rect = { 0, 0, settings_.initial_width, settings_.initial_height };
+ AdjustWindowRect(&win_rect, win_style, false);
+
+ hwnd_ = CreateWindowEx(WS_EX_APPWINDOW,
+ class_name.c_str(),
+ settings_.name.c_str(),
+ win_style,
+ 0,
+ 0,
+ win_rect.right - win_rect.left,
+ win_rect.bottom - win_rect.top,
+ nullptr,
+ nullptr,
+ hinstance_,
+ nullptr);
+
+ SetForegroundWindow(hwnd_);
+ SetWindowLongPtr(hwnd_, GWLP_USERDATA, (LONG_PTR) this);
+}
+
+PFN_vkGetInstanceProcAddr ShellWin32::load_vk()
+{
+ const char filename[] = "vulkan-1.dll";
+ HMODULE mod;
+ PFN_vkGetInstanceProcAddr get_proc;
+
+ mod = LoadLibrary(filename);
+ if (mod) {
+ get_proc = reinterpret_cast<PFN_vkGetInstanceProcAddr>(GetProcAddress(
+ mod, "vkGetInstanceProcAddr"));
+ }
+
+ if (!mod || !get_proc) {
+ std::stringstream ss;
+ ss << "failed to load " << filename;
+
+ if (mod)
+ FreeLibrary(mod);
+
+ throw std::runtime_error(ss.str());
+ }
+
+ hmodule_ = mod;
+
+ return get_proc;
+}
+
+bool ShellWin32::can_present(VkPhysicalDevice phy, uint32_t queue_family)
+{
+ return vk::GetPhysicalDeviceWin32PresentationSupportKHR(phy, queue_family);
+}
+
+VkSurfaceKHR ShellWin32::create_surface(VkInstance instance)
+{
+ VkWin32SurfaceCreateInfoKHR surface_info = {};
+ surface_info.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
+ surface_info.hinstance = hinstance_;
+ surface_info.hwnd = hwnd_;
+
+ VkSurfaceKHR surface;
+ vk::assert_success(vk::CreateWin32SurfaceKHR(instance, &surface_info, nullptr, &surface));
+
+ return surface;
+}
+
+LRESULT ShellWin32::handle_message(UINT msg, WPARAM wparam, LPARAM lparam)
+{
+ switch (msg) {
+ case WM_SIZE:
+ {
+ UINT w = LOWORD(lparam);
+ UINT h = HIWORD(lparam);
+ resize_swapchain(w, h);
+ }
+ break;
+ case WM_KEYDOWN:
+ {
+ Game::Key key;
+
+ switch (wparam) {
+ case VK_ESCAPE:
+ key = Game::KEY_ESC;
+ break;
+ case VK_UP:
+ key = Game::KEY_UP;
+ break;
+ case VK_DOWN:
+ key = Game::KEY_DOWN;
+ break;
+ case VK_SPACE:
+ key = Game::KEY_SPACE;
+ break;
+ default:
+ key = Game::KEY_UNKNOWN;
+ break;
+ }
+
+ game_.on_key(key);
+ }
+ break;
+ case WM_CLOSE:
+ game_.on_key(Game::KEY_SHUTDOWN);
+ break;
+ case WM_DESTROY:
+ quit();
+ break;
+ default:
+ return DefWindowProc(hwnd_, msg, wparam, lparam);
+ break;
+ }
+
+ return 0;
+}
+
+void ShellWin32::quit()
+{
+ PostQuitMessage(0);
+}
+
+void ShellWin32::run()
+{
+ create_window();
+
+ create_context();
+ resize_swapchain(settings_.initial_width, settings_.initial_height);
+
+ Win32Timer timer;
+ double current_time = timer.get();
+
+ while (true) {
+ bool quit = false;
+
+ assert(settings_.animate);
+
+ // process all messages
+ MSG msg;
+ while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
+ if (msg.message == WM_QUIT) {
+ quit = true;
+ break;
+ }
+
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+
+ if (quit)
+ break;
+
+ acquire_back_buffer();
+
+ double t = timer.get();
+ add_game_time(static_cast<float>(t - current_time));
+
+ present_back_buffer();
+
+ current_time = t;
+ }
+
+ destroy_context();
+
+ DestroyWindow(hwnd_);
+}
diff --git a/demos/smoke/ShellWin32.h b/demos/smoke/ShellWin32.h
new file mode 100644
index 00000000..c5a136bd
--- /dev/null
+++ b/demos/smoke/ShellWin32.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2016 Google, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef SHELL_WIN32_H
+#define SHELL_WIN32_H
+
+#include <windows.h>
+#include "Shell.h"
+
+class ShellWin32 : public Shell {
+public:
+ ShellWin32(Game &game);
+ ~ShellWin32();
+
+ void run();
+ void quit();
+
+private:
+
+ PFN_vkGetInstanceProcAddr load_vk();
+ bool can_present(VkPhysicalDevice phy, uint32_t queue_family);
+
+ void create_window();
+ VkSurfaceKHR create_surface(VkInstance instance);
+
+ static LRESULT CALLBACK window_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ ShellWin32 *shell = reinterpret_cast<ShellWin32 *>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
+
+ // called from constructor, CreateWindowEx specifically. But why?
+ if (!shell)
+ return DefWindowProc(hwnd, uMsg, wParam, lParam);
+
+ return shell->handle_message(uMsg, wParam, lParam);
+ }
+ LRESULT handle_message(UINT msg, WPARAM wparam, LPARAM lparam);
+
+ HINSTANCE hinstance_;
+ HWND hwnd_;
+
+ HMODULE hmodule_;
+};
+
+#endif // SHELL_WIN32_H
diff --git a/demos/smoke/ShellXcb.cpp b/demos/smoke/ShellXcb.cpp
new file mode 100644
index 00000000..e8389674
--- /dev/null
+++ b/demos/smoke/ShellXcb.cpp
@@ -0,0 +1,344 @@
+/*
+ * Copyright (C) 2016 Google, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <cassert>
+#include <sstream>
+#include <dlfcn.h>
+#include <time.h>
+
+#include "Helpers.h"
+#include "Game.h"
+#include "ShellXcb.h"
+
+namespace {
+
+class PosixTimer {
+public:
+ PosixTimer()
+ {
+ reset();
+ }
+
+ void reset()
+ {
+ clock_gettime(CLOCK_MONOTONIC, &start_);
+ }
+
+ double get() const
+ {
+ struct timespec now;
+ clock_gettime(CLOCK_MONOTONIC, &now);
+
+ constexpr long one_s_in_ns = 1000 * 1000 * 1000;
+ constexpr double one_s_in_ns_d = static_cast<double>(one_s_in_ns);
+
+ time_t s = now.tv_sec - start_.tv_sec;
+ long ns;
+ if (now.tv_nsec > start_.tv_nsec) {
+ ns = now.tv_nsec - start_.tv_nsec;
+ } else {
+ assert(s > 0);
+ s--;
+ ns = one_s_in_ns - (start_.tv_nsec - now.tv_nsec);
+ }
+
+ return static_cast<double>(s) + static_cast<double>(ns) / one_s_in_ns_d;
+ }
+
+private:
+ struct timespec start_;
+};
+
+xcb_intern_atom_cookie_t intern_atom_cookie(xcb_connection_t *c, const std::string &s)
+{
+ return xcb_intern_atom(c, false, s.size(), s.c_str());
+}
+
+xcb_atom_t intern_atom(xcb_connection_t *c, xcb_intern_atom_cookie_t cookie)
+{
+ xcb_atom_t atom = XCB_ATOM_NONE;
+ xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(c, cookie, nullptr);
+ if (reply) {
+ atom = reply->atom;
+ free(reply);
+ }
+
+ return atom;
+}
+
+} // namespace
+
+ShellXcb::ShellXcb(Game &game) : Shell(game)
+{
+ instance_extensions_.push_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
+
+ init_connection();
+ init_vk();
+}
+
+ShellXcb::~ShellXcb()
+{
+ cleanup_vk();
+ dlclose(lib_handle_);
+
+ xcb_disconnect(c_);
+}
+
+void ShellXcb::init_connection()
+{
+ int scr;
+
+ c_ = xcb_connect(nullptr, &scr);
+ if (!c_ || xcb_connection_has_error(c_)) {
+ xcb_disconnect(c_);
+ throw std::runtime_error("failed to connect to the display server");
+ }
+
+ const xcb_setup_t *setup = xcb_get_setup(c_);
+ xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup);
+ while (scr-- > 0)
+ xcb_screen_next(&iter);
+
+ scr_ = iter.data;
+}
+
+void ShellXcb::create_window()
+{
+ win_ = xcb_generate_id(c_);
+
+ uint32_t value_mask, value_list[32];
+ value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
+ value_list[0] = scr_->black_pixel;
+ value_list[1] = XCB_EVENT_MASK_KEY_PRESS |
+ XCB_EVENT_MASK_STRUCTURE_NOTIFY;
+
+ xcb_create_window(c_,
+ XCB_COPY_FROM_PARENT,
+ win_, scr_->root, 0, 0,
+ settings_.initial_width, settings_.initial_height, 0,
+ XCB_WINDOW_CLASS_INPUT_OUTPUT,
+ scr_->root_visual,
+ value_mask, value_list);
+
+ xcb_intern_atom_cookie_t utf8_string_cookie = intern_atom_cookie(c_, "UTF8_STRING");
+ xcb_intern_atom_cookie_t _net_wm_name_cookie = intern_atom_cookie(c_, "_NET_WM_NAME");
+ xcb_intern_atom_cookie_t wm_protocols_cookie = intern_atom_cookie(c_, "WM_PROTOCOLS");
+ xcb_intern_atom_cookie_t wm_delete_window_cookie = intern_atom_cookie(c_, "WM_DELETE_WINDOW");
+
+ // set title
+ xcb_atom_t utf8_string = intern_atom(c_, utf8_string_cookie);
+ xcb_atom_t _net_wm_name = intern_atom(c_, _net_wm_name_cookie);
+ xcb_change_property(c_, XCB_PROP_MODE_REPLACE, win_, _net_wm_name,
+ utf8_string, 8, settings_.name.size(), settings_.name.c_str());
+
+ // advertise WM_DELETE_WINDOW
+ wm_protocols_ = intern_atom(c_, wm_protocols_cookie);
+ wm_delete_window_ = intern_atom(c_, wm_delete_window_cookie);
+ xcb_change_property(c_, XCB_PROP_MODE_REPLACE, win_, wm_protocols_,
+ XCB_ATOM_ATOM, 32, 1, &wm_delete_window_);
+}
+
+PFN_vkGetInstanceProcAddr ShellXcb::load_vk()
+{
+ const char filename[] = "libvulkan.so";
+ void *handle, *symbol;
+
+#ifdef UNINSTALLED_LOADER
+ handle = dlopen(UNINSTALLED_LOADER, RTLD_LAZY);
+ if (!handle)
+ handle = dlopen(filename, RTLD_LAZY);
+#else
+ handle = dlopen(filename, RTLD_LAZY);
+#endif
+
+ if (handle)
+ symbol = dlsym(handle, "vkGetInstanceProcAddr");
+
+ if (!handle || !symbol) {
+ std::stringstream ss;
+ ss << "failed to load " << dlerror();
+
+ if (handle)
+ dlclose(handle);
+
+ throw std::runtime_error(ss.str());
+ }
+
+ lib_handle_ = handle;
+
+ return reinterpret_cast<PFN_vkGetInstanceProcAddr>(symbol);
+}
+
+bool ShellXcb::can_present(VkPhysicalDevice phy, uint32_t queue_family)
+{
+ return vk::GetPhysicalDeviceXcbPresentationSupportKHR(phy,
+ queue_family, c_, scr_->root_visual);
+}
+
+VkSurfaceKHR ShellXcb::create_surface(VkInstance instance)
+{
+ VkXcbSurfaceCreateInfoKHR surface_info = {};
+ surface_info.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
+ surface_info.connection = c_;
+ surface_info.window = win_;
+
+ VkSurfaceKHR surface;
+ vk::assert_success(vk::CreateXcbSurfaceKHR(instance, &surface_info, nullptr, &surface));
+
+ return surface;
+}
+
+void ShellXcb::handle_event(const xcb_generic_event_t *ev)
+{
+ switch (ev->response_type & 0x7f) {
+ case XCB_CONFIGURE_NOTIFY:
+ {
+ const xcb_configure_notify_event_t *notify =
+ reinterpret_cast<const xcb_configure_notify_event_t *>(ev);
+ resize_swapchain(notify->width, notify->height);
+ }
+ break;
+ case XCB_KEY_PRESS:
+ {
+ const xcb_key_press_event_t *press =
+ reinterpret_cast<const xcb_key_press_event_t *>(ev);
+ Game::Key key;
+
+ // TODO translate xcb_keycode_t
+ switch (press->detail) {
+ case 9:
+ key = Game::KEY_ESC;
+ break;
+ case 111:
+ key = Game::KEY_UP;
+ break;
+ case 116:
+ key = Game::KEY_DOWN;
+ break;
+ case 65:
+ key = Game::KEY_SPACE;
+ break;
+ default:
+ key = Game::KEY_UNKNOWN;
+ break;
+ }
+
+ game_.on_key(key);
+ }
+ break;
+ case XCB_CLIENT_MESSAGE:
+ {
+ const xcb_client_message_event_t *msg =
+ reinterpret_cast<const xcb_client_message_event_t *>(ev);
+ if (msg->type == wm_protocols_ && msg->data.data32[0] == wm_delete_window_)
+ game_.on_key(Game::KEY_SHUTDOWN);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void ShellXcb::loop_wait()
+{
+ while (true) {
+ xcb_generic_event_t *ev = xcb_wait_for_event(c_);
+ if (!ev)
+ continue;
+
+ handle_event(ev);
+ free(ev);
+
+ if (quit_)
+ break;
+
+ acquire_back_buffer();
+ present_back_buffer();
+ }
+}
+
+void ShellXcb::loop_poll()
+{
+ PosixTimer timer;
+
+ double current_time = timer.get();
+ double profile_start_time = current_time;
+ int profile_present_count = 0;
+
+ while (true) {
+ // handle pending events
+ while (true) {
+ xcb_generic_event_t *ev = xcb_poll_for_event(c_);
+ if (!ev)
+ break;
+
+ handle_event(ev);
+ free(ev);
+ }
+
+ if (quit_)
+ break;
+
+ acquire_back_buffer();
+
+ double t = timer.get();
+ add_game_time(static_cast<float>(t - current_time));
+
+ present_back_buffer();
+
+ current_time = t;
+
+ profile_present_count++;
+ if (current_time - profile_start_time >= 5.0) {
+ const double fps = profile_present_count / (current_time - profile_start_time);
+ std::stringstream ss;
+ ss << profile_present_count << " presents in " <<
+ current_time - profile_start_time << " seconds " <<
+ "(FPS: " << fps << ")";
+ log(LOG_INFO, ss.str().c_str());
+
+ profile_start_time = current_time;
+ profile_present_count = 0;
+ }
+ }
+}
+
+void ShellXcb::run()
+{
+ create_window();
+ xcb_map_window(c_, win_);
+ xcb_flush(c_);
+
+ create_context();
+ resize_swapchain(settings_.initial_width, settings_.initial_height);
+
+ quit_ = false;
+ if (settings_.animate)
+ loop_poll();
+ else
+ loop_wait();
+
+ destroy_context();
+
+ xcb_destroy_window(c_, win_);
+ xcb_flush(c_);
+}
diff --git a/demos/smoke/ShellXcb.h b/demos/smoke/ShellXcb.h
new file mode 100644
index 00000000..89f9a436
--- /dev/null
+++ b/demos/smoke/ShellXcb.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2016 Google, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef SHELL_XCB_H
+#define SHELL_XCB_H
+
+#include <xcb/xcb.h>
+#include "Shell.h"
+
+class ShellXcb : public Shell {
+public:
+ ShellXcb(Game &game);
+ ~ShellXcb();
+
+ void run();
+ void quit() { quit_ = true; }
+
+private:
+ void init_connection();
+
+ PFN_vkGetInstanceProcAddr load_vk();
+ bool can_present(VkPhysicalDevice phy, uint32_t queue_family);
+
+ void create_window();
+ VkSurfaceKHR create_surface(VkInstance instance);
+
+ void handle_event(const xcb_generic_event_t *ev);
+ void loop_wait();
+ void loop_poll();
+
+ xcb_connection_t *c_;
+ xcb_screen_t *scr_;
+ xcb_window_t win_;
+
+ xcb_atom_t wm_protocols_;
+ xcb_atom_t wm_delete_window_;
+
+ void *lib_handle_;
+
+ bool quit_;
+};
+
+#endif // SHELL_XCB_H
diff --git a/demos/smoke/Simulation.cpp b/demos/smoke/Simulation.cpp
new file mode 100644
index 00000000..dab45d70
--- /dev/null
+++ b/demos/smoke/Simulation.cpp
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2016 Google, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <cassert>
+#include <cmath>
+#include <array>
+#include <glm/gtc/matrix_transform.hpp>
+#include "Simulation.h"
+
+namespace {
+
+class MeshPicker {
+public:
+ MeshPicker() :
+ pattern_({
+ Meshes::MESH_PYRAMID,
+ Meshes::MESH_ICOSPHERE,
+ Meshes::MESH_TEAPOT,
+ Meshes::MESH_PYRAMID,
+ Meshes::MESH_ICOSPHERE,
+ Meshes::MESH_PYRAMID,
+ Meshes::MESH_PYRAMID,
+ Meshes::MESH_PYRAMID,
+ Meshes::MESH_PYRAMID,
+ Meshes::MESH_PYRAMID,
+ }), cur_(-1)
+ {
+ }
+
+ Meshes::Type pick()
+ {
+ cur_ = (cur_ + 1) % pattern_.size();
+ return pattern_[cur_];
+ }
+
+ float scale(Meshes::Type type) const
+ {
+ float base = 0.005f;
+
+ switch (type) {
+ case Meshes::MESH_PYRAMID:
+ default:
+ return base * 1.0f;
+ case Meshes::MESH_ICOSPHERE:
+ return base * 3.0f;
+ case Meshes::MESH_TEAPOT:
+ return base * 10.0f;
+ }
+ }
+
+private:
+ const std::array<Meshes::Type, 10> pattern_;
+ int cur_;
+};
+
+class ColorPicker {
+public:
+ ColorPicker(unsigned int rng_seed) :
+ rng_(rng_seed),
+ red_(0.0f, 1.0f),
+ green_(0.0f, 1.0f),
+ blue_(0.0f, 1.0f)
+ {
+ }
+
+ glm::vec3 pick()
+ {
+ return glm::vec3{ red_(rng_),
+ green_(rng_),
+ blue_(rng_) };
+ }
+
+private:
+ std::mt19937 rng_;
+ std::uniform_real_distribution<float> red_;
+ std::uniform_real_distribution<float> green_;
+ std::uniform_real_distribution<float> blue_;
+};
+
+} // namespace
+
+Animation::Animation(unsigned int rng_seed, float scale)
+ : rng_(rng_seed), dir_(-1.0f, 1.0f), speed_(0.1f, 1.0f)
+{
+ float x = dir_(rng_);
+ float y = dir_(rng_);
+ float z = dir_(rng_);
+ if (std::abs(x) + std::abs(y) + std::abs(z) == 0.0f)
+ x = 1.0f;
+
+ current_.axis = glm::normalize(glm::vec3(x, y, z));
+
+ current_.speed = speed_(rng_);
+ current_.scale = scale;
+
+ current_.matrix = glm::scale(glm::mat4(1.0f), glm::vec3(current_.scale));
+}
+
+glm::mat4 Animation::transformation(float t)
+{
+ current_.matrix = glm::rotate(current_.matrix, current_.speed * t, current_.axis);
+
+ return current_.matrix;
+}
+
+class Curve {
+public:
+ virtual ~Curve() {}
+ virtual glm::vec3 evaluate(float t) = 0;
+};
+
+namespace {
+
+enum CurveType {
+ CURVE_RANDOM,
+ CURVE_CIRCLE,
+ CURVE_COUNT,
+};
+
+class RandomCurve : public Curve {
+public:
+ RandomCurve(unsigned int rng_seed)
+ : rng_(rng_seed), direction_(-0.3f, 0.3f), duration_(1.0f, 5.0f),
+ segment_start_(0.0f), segment_direction_(0.0f),
+ time_start_(0.0f), time_duration_(0.0f)
+ {
+ }
+
+ glm::vec3 evaluate(float t)
+ {
+ if (t >= time_start_ + time_duration_)
+ new_segment(t);
+
+ pos_ += unit_dir_ * (t - last_);
+ last_ = t;
+
+ return pos_;
+ }
+
+private:
+ void new_segment(float time_start)
+ {
+ segment_start_ += segment_direction_;
+ segment_direction_ = glm::vec3(direction_(rng_),
+ direction_(rng_),
+ direction_(rng_));
+
+ time_start_ = time_start;
+ time_duration_ = duration_(rng_);
+
+ unit_dir_ = segment_direction_ / time_duration_;
+ pos_ = segment_start_;
+ last_ = time_start_;
+ }
+
+ std::mt19937 rng_;
+ std::uniform_real_distribution<float> direction_;
+ std::uniform_real_distribution<float> duration_;
+
+ glm::vec3 segment_start_;
+ glm::vec3 segment_direction_;
+ float time_start_;
+ float time_duration_;
+
+ glm::vec3 unit_dir_;
+ glm::vec3 pos_;
+ float last_;
+};
+
+class CircleCurve : public Curve {
+public:
+ CircleCurve(float radius, glm::vec3 axis)
+ : r_(radius)
+ {
+ glm::vec3 a;
+
+ if (axis.x != 0.0f) {
+ a.x = -axis.z / axis.x;
+ a.y = 0.0f;
+ a.z = 1.0f;
+ } else if (axis.y != 0.0f) {
+ a.x = 1.0f;
+ a.y = -axis.x / axis.y;
+ a.z = 0.0f;
+ } else {
+ a.x = 1.0f;
+ a.y = 0.0f;
+ a.z = -axis.x / axis.z;
+ }
+
+ a_ = glm::normalize(a);
+ b_ = glm::normalize(glm::cross(a_, axis));
+ }
+
+ glm::vec3 evaluate(float t)
+ {
+ return (a_ * (glm::vec3(std::cos(t)) - glm::vec3(1.0f)) + b_ * glm::vec3(std::sin(t))) *
+ glm::vec3(r_);
+ }
+
+private:
+ float r_;
+ glm::vec3 a_;
+ glm::vec3 b_;
+};
+
+} // namespace
+
+Path::Path(unsigned int rng_seed)
+ : rng_(rng_seed), type_(0, CURVE_COUNT - 1), duration_(5.0f, 20.0f)
+{
+ // trigger a subpath generation
+ current_.end = -1.0f;
+ current_.now = 0.0f;
+}
+
+glm::vec3 Path::position(float t)
+{
+ current_.now += t;
+
+ while (current_.now >= current_.end)
+ generate_subpath();
+
+ return current_.origin + current_.curve->evaluate(current_.now - current_.start);
+}
+
+void Path::generate_subpath()
+{
+ float duration = duration_(rng_);
+ CurveType type = static_cast<CurveType>(type_(rng_));
+
+ if (current_.curve) {
+ current_.origin += current_.curve->evaluate(current_.end - current_.start);
+ current_.start = current_.end;
+ } else {
+ std::uniform_real_distribution<float> origin(0.0f, 2.0f);
+ current_.origin = glm::vec3(origin(rng_), origin(rng_), origin(rng_));
+ current_.start = current_.now;
+ }
+
+ current_.end = current_.start + duration;
+
+ Curve *curve;
+
+ switch (type) {
+ case CURVE_RANDOM:
+ curve = new RandomCurve(rng_());
+ break;
+ case CURVE_CIRCLE:
+ {
+ std::uniform_real_distribution<float> dir(-1.0f, 1.0f);
+ glm::vec3 axis(dir(rng_), dir(rng_), dir(rng_));
+ if (axis.x == 0.0f && axis.y == 0.0f && axis.z == 0.0f)
+ axis.x = 1.0f;
+
+ std::uniform_real_distribution<float> radius_(0.02f, 0.2f);
+ curve = new CircleCurve(radius_(rng_), axis);
+ }
+ break;
+ default:
+ assert(!"unreachable");
+ curve = nullptr;
+ break;
+ }
+
+ current_.curve.reset(curve);
+}
+
+Simulation::Simulation(int object_count)
+ : random_dev_()
+{
+ MeshPicker mesh;
+ ColorPicker color(random_dev_());
+
+ objects_.reserve(object_count);
+ for (int i = 0; i < object_count; i++) {
+ Meshes::Type type = mesh.pick();
+ float scale = mesh.scale(type);
+
+ objects_.emplace_back(Object{
+ type,
+ glm::vec3(0.5 + 0.5 * (float) i / object_count),
+ color.pick(),
+ Animation(random_dev_(), scale),
+ Path(random_dev_()),
+ });
+ }
+}
+
+void Simulation::set_frame_data_size(uint32_t size)
+{
+ uint32_t offset = 0;
+ for (auto &obj : objects_) {
+ obj.frame_data_offset = offset;
+ offset += size;
+ }
+}
+
+void Simulation::update(float time, int begin, int end)
+{
+ for (int i = begin; i < end; i++) {
+ auto &obj = objects_[i];
+
+ glm::vec3 pos = obj.path.position(time);
+ glm::mat4 trans = obj.animation.transformation(time);
+ obj.model = glm::translate(glm::mat4(1.0f), pos) * trans;
+ }
+}
diff --git a/demos/smoke/Simulation.h b/demos/smoke/Simulation.h
new file mode 100644
index 00000000..31241f9c
--- /dev/null
+++ b/demos/smoke/Simulation.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2016 Google, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef SIMULATION_H
+#define SIMULATION_H
+
+#include <memory>
+#include <random>
+#include <vector>
+
+#include <glm/glm.hpp>
+
+#include "Meshes.h"
+
+class Animation {
+public:
+ Animation(unsigned rng_seed, float scale);
+
+ glm::mat4 transformation(float t);
+
+private:
+ struct Data {
+ glm::vec3 axis;
+ float speed;
+ float scale;
+
+ glm::mat4 matrix;
+ };
+
+ std::mt19937 rng_;
+ std::uniform_real_distribution<float> dir_;
+ std::uniform_real_distribution<float> speed_;
+
+ Data current_;
+};
+
+class Curve;
+
+class Path {
+public:
+ Path(unsigned rng_seed);
+
+ glm::vec3 position(float t);
+
+private:
+ struct Subpath {
+ glm::vec3 origin;
+ float start;
+ float end;
+ float now;
+
+ std::shared_ptr<Curve> curve;
+ };
+
+ void generate_subpath();
+
+ std::mt19937 rng_;
+ std::uniform_int_distribution<> type_;
+ std::uniform_real_distribution<float> duration_;
+
+ Subpath current_;
+};
+
+class Simulation {
+public:
+ Simulation(int object_count);
+
+ struct Object {
+ Meshes::Type mesh;
+ glm::vec3 light_pos;
+ glm::vec3 light_color;
+
+ Animation animation;
+ Path path;
+
+ uint32_t frame_data_offset;
+
+ glm::mat4 model;
+ };
+
+ const std::vector<Object> &objects() const { return objects_; }
+
+ unsigned int rng_seed() { return random_dev_(); }
+
+ void set_frame_data_size(uint32_t size);
+ void update(float time, int begin, int end);
+
+private:
+ std::random_device random_dev_;
+ std::vector<Object> objects_;
+};
+
+#endif // SIMULATION_H
diff --git a/demos/smoke/Smoke.cpp b/demos/smoke/Smoke.cpp
new file mode 100644
index 00000000..ed6e0178
--- /dev/null
+++ b/demos/smoke/Smoke.cpp
@@ -0,0 +1,915 @@
+/*
+ * Copyright (C) 2016 Google, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <array>
+
+#include <glm/gtc/type_ptr.hpp>
+#include <glm/gtc/matrix_transform.hpp>
+
+#include "Helpers.h"
+#include "Smoke.h"
+#include "Meshes.h"
+#include "Shell.h"
+
+namespace {
+
+// TODO do not rely on compiler to use std140 layout
+// TODO move lower frequency data to another descriptor set
+struct ShaderParamBlock {
+ float light_pos[4];
+ float light_color[4];
+ float model[4 * 4];
+ float view_projection[4 * 4];
+};
+
+} // namespace
+
+Smoke::Smoke(const std::vector<std::string> &args)
+ : Game("Smoke", args), multithread_(true), use_push_constants_(false),
+ sim_paused_(false), sim_(5000), camera_(2.5f), frame_data_(),
+ render_pass_clear_value_({{ 0.0f, 0.1f, 0.2f, 1.0f }}),
+ render_pass_begin_info_(),
+ primary_cmd_begin_info_(), primary_cmd_submit_info_()
+{
+ for (auto it = args.begin(); it != args.end(); ++it) {
+ if (*it == "-s")
+ multithread_ = false;
+ else if (*it == "-p")
+ use_push_constants_ = true;
+ }
+
+ init_workers();
+}
+
+Smoke::~Smoke()
+{
+}
+
+void Smoke::init_workers()
+{
+ int worker_count = std::thread::hardware_concurrency();
+
+ // not enough cores
+ if (!multithread_ || worker_count < 2) {
+ multithread_ = false;
+ worker_count = 1;
+ }
+
+ const int object_per_worker = sim_.objects().size() / worker_count;
+ int object_begin = 0, object_end = 0;
+
+ workers_.reserve(worker_count);
+ for (int i = 0; i < worker_count; i++) {
+ object_begin = object_end;
+ if (i < worker_count - 1)
+ object_end += object_per_worker;
+ else
+ object_end = sim_.objects().size();
+
+ Worker *worker = new Worker(*this, i, object_begin, object_end);
+ workers_.emplace_back(std::unique_ptr<Worker>(worker));
+ }
+}
+
+void Smoke::attach_shell(Shell &sh)
+{
+ Game::attach_shell(sh);
+
+ const Shell::Context &ctx = sh.context();
+ physical_dev_ = ctx.physical_dev;
+ dev_ = ctx.dev;
+ queue_ = ctx.game_queue;
+ queue_family_ = ctx.game_queue_family;
+ format_ = ctx.format.format;
+
+ vk::GetPhysicalDeviceProperties(physical_dev_, &physical_dev_props_);
+
+ if (use_push_constants_ &&
+ sizeof(ShaderParamBlock) > physical_dev_props_.limits.maxPushConstantsSize) {
+ shell_->log(Shell::LOG_WARN, "cannot enable push constants");
+ use_push_constants_ = false;
+ }
+
+ VkPhysicalDeviceMemoryProperties mem_props;
+ vk::GetPhysicalDeviceMemoryProperties(physical_dev_, &mem_props);
+ mem_flags_.reserve(mem_props.memoryTypeCount);
+ for (uint32_t i = 0; i < mem_props.memoryTypeCount; i++)
+ mem_flags_.push_back(mem_props.memoryTypes[i].propertyFlags);
+
+ meshes_ = new Meshes(dev_, mem_flags_);
+
+ create_render_pass();
+ create_shader_modules();
+ create_descriptor_set_layout();
+ create_pipeline_layout();
+ create_pipeline();
+
+ create_frame_data(2);
+
+ render_pass_begin_info_.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+ render_pass_begin_info_.renderPass = render_pass_;
+ render_pass_begin_info_.clearValueCount = 1;
+ render_pass_begin_info_.pClearValues = &render_pass_clear_value_;
+
+ primary_cmd_begin_info_.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ primary_cmd_begin_info_.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
+
+ // we will render to the swapchain images
+ primary_cmd_submit_wait_stages_ = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+
+ primary_cmd_submit_info_.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ primary_cmd_submit_info_.waitSemaphoreCount = 1;
+ primary_cmd_submit_info_.pWaitDstStageMask = &primary_cmd_submit_wait_stages_;
+ primary_cmd_submit_info_.commandBufferCount = 1;
+ primary_cmd_submit_info_.signalSemaphoreCount = 1;
+
+ if (multithread_) {
+ for (auto &worker : workers_)
+ worker->start();
+ }
+}
+
+void Smoke::detach_shell()
+{
+ if (multithread_) {
+ for (auto &worker : workers_)
+ worker->stop();
+ }
+
+ destroy_frame_data();
+
+ vk::DestroyPipeline(dev_, pipeline_, nullptr);
+ vk::DestroyPipelineLayout(dev_, pipeline_layout_, nullptr);
+ if (!use_push_constants_)
+ vk::DestroyDescriptorSetLayout(dev_, desc_set_layout_, nullptr);
+ vk::DestroyShaderModule(dev_, fs_, nullptr);
+ vk::DestroyShaderModule(dev_, vs_, nullptr);
+ vk::DestroyRenderPass(dev_, render_pass_, nullptr);
+
+ delete meshes_;
+
+ Game::detach_shell();
+}
+
+void Smoke::create_render_pass()
+{
+ VkAttachmentDescription attachment = {};
+ attachment.format = format_;
+ attachment.samples = VK_SAMPLE_COUNT_1_BIT;
+ attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+
+ VkAttachmentReference attachment_ref = {};
+ attachment_ref.attachment = 0;
+ attachment_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+ VkSubpassDescription subpass = {};
+ subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+ subpass.colorAttachmentCount = 1;
+ subpass.pColorAttachments = &attachment_ref;
+
+ std::array<VkSubpassDependency, 2> subpass_deps;
+ subpass_deps[0].srcSubpass = VK_SUBPASS_EXTERNAL;
+ subpass_deps[0].dstSubpass = 0;
+ subpass_deps[0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+ subpass_deps[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ subpass_deps[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT;
+ subpass_deps[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
+ VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+ subpass_deps[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
+
+ subpass_deps[1].srcSubpass = 0;
+ subpass_deps[1].dstSubpass = VK_SUBPASS_EXTERNAL;
+ subpass_deps[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ subpass_deps[1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+ subpass_deps[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
+ VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+ subpass_deps[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
+ subpass_deps[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
+
+ VkRenderPassCreateInfo render_pass_info = {};
+ render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
+ render_pass_info.attachmentCount = 1;
+ render_pass_info.pAttachments = &attachment;
+ render_pass_info.subpassCount = 1;
+ render_pass_info.pSubpasses = &subpass;
+ render_pass_info.dependencyCount = (uint32_t)subpass_deps.size();
+ render_pass_info.pDependencies = subpass_deps.data();
+
+ vk::assert_success(vk::CreateRenderPass(dev_, &render_pass_info, nullptr, &render_pass_));
+}
+
+void Smoke::create_shader_modules()
+{
+ VkShaderModuleCreateInfo sh_info = {};
+ sh_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
+ if (use_push_constants_) {
+#include "Smoke.push_constant.vert.h"
+ sh_info.codeSize = sizeof(Smoke_push_constant_vert);
+ sh_info.pCode = Smoke_push_constant_vert;
+ } else {
+#include "Smoke.vert.h"
+ sh_info.codeSize = sizeof(Smoke_vert);
+ sh_info.pCode = Smoke_vert;
+ }
+ vk::assert_success(vk::CreateShaderModule(dev_, &sh_info, nullptr, &vs_));
+
+#include "Smoke.frag.h"
+ sh_info.codeSize = sizeof(Smoke_frag);
+ sh_info.pCode = Smoke_frag;
+ vk::assert_success(vk::CreateShaderModule(dev_, &sh_info, nullptr, &fs_));
+}
+
+void Smoke::create_descriptor_set_layout()
+{
+ if (use_push_constants_)
+ return;
+
+ VkDescriptorSetLayoutBinding layout_binding = {};
+ layout_binding.binding = 0;
+ layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
+ layout_binding.descriptorCount = 1;
+ layout_binding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
+
+ VkDescriptorSetLayoutCreateInfo layout_info = {};
+ layout_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
+ layout_info.bindingCount = 1;
+ layout_info.pBindings = &layout_binding;
+
+ vk::assert_success(vk::CreateDescriptorSetLayout(dev_, &layout_info,
+ nullptr, &desc_set_layout_));
+}
+
+void Smoke::create_pipeline_layout()
+{
+ VkPushConstantRange push_const_range = {};
+
+ VkPipelineLayoutCreateInfo pipeline_layout_info = {};
+ pipeline_layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
+
+ if (use_push_constants_) {
+ push_const_range.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
+ push_const_range.offset = 0;
+ push_const_range.size = sizeof(ShaderParamBlock);
+
+ pipeline_layout_info.pushConstantRangeCount = 1;
+ pipeline_layout_info.pPushConstantRanges = &push_const_range;
+ } else {
+ pipeline_layout_info.setLayoutCount = 1;
+ pipeline_layout_info.pSetLayouts = &desc_set_layout_;
+ }
+
+ vk::assert_success(vk::CreatePipelineLayout(dev_, &pipeline_layout_info,
+ nullptr, &pipeline_layout_));
+}
+
+void Smoke::create_pipeline()
+{
+ VkPipelineShaderStageCreateInfo stage_info[2] = {};
+ stage_info[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
+ stage_info[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
+ stage_info[0].module = vs_;
+ stage_info[0].pName = "main";
+ stage_info[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
+ stage_info[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
+ stage_info[1].module = fs_;
+ stage_info[1].pName = "main";
+
+ VkPipelineViewportStateCreateInfo viewport_info = {};
+ viewport_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
+ // both dynamic
+ viewport_info.viewportCount = 1;
+ viewport_info.scissorCount = 1;
+
+ VkPipelineRasterizationStateCreateInfo rast_info = {};
+ rast_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
+ rast_info.depthClampEnable = false;
+ rast_info.rasterizerDiscardEnable = false;
+ rast_info.polygonMode = VK_POLYGON_MODE_FILL;
+ rast_info.cullMode = VK_CULL_MODE_NONE;
+ rast_info.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
+ rast_info.depthBiasEnable = false;
+ rast_info.lineWidth = 1.0f;
+
+ VkPipelineMultisampleStateCreateInfo multisample_info = {};
+ multisample_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
+ multisample_info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
+ multisample_info.sampleShadingEnable = false;
+ multisample_info.pSampleMask = nullptr;
+ multisample_info.alphaToCoverageEnable = false;
+ multisample_info.alphaToOneEnable = false;
+
+ VkPipelineColorBlendAttachmentState blend_attachment = {};
+ blend_attachment.blendEnable = true;
+ blend_attachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
+ blend_attachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
+ blend_attachment.colorBlendOp = VK_BLEND_OP_ADD;
+ blend_attachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
+ blend_attachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
+ blend_attachment.alphaBlendOp = VK_BLEND_OP_ADD;
+ blend_attachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT |
+ VK_COLOR_COMPONENT_G_BIT |
+ VK_COLOR_COMPONENT_B_BIT |
+ VK_COLOR_COMPONENT_A_BIT;
+
+ VkPipelineColorBlendStateCreateInfo blend_info = {};
+ blend_info.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
+ blend_info.logicOpEnable = false;
+ blend_info.attachmentCount = 1;
+ blend_info.pAttachments = &blend_attachment;
+
+ std::array<VkDynamicState, 2> dynamic_states = {
+ VK_DYNAMIC_STATE_VIEWPORT,
+ VK_DYNAMIC_STATE_SCISSOR
+ };
+ struct VkPipelineDynamicStateCreateInfo dynamic_info = {};
+ dynamic_info.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
+ dynamic_info.dynamicStateCount = (uint32_t)dynamic_states.size();
+ dynamic_info.pDynamicStates = dynamic_states.data();
+
+ VkGraphicsPipelineCreateInfo pipeline_info = {};
+ pipeline_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
+ pipeline_info.stageCount = 2;
+ pipeline_info.pStages = stage_info;
+ pipeline_info.pVertexInputState = &meshes_->vertex_input_state();
+ pipeline_info.pInputAssemblyState = &meshes_->input_assembly_state();
+ pipeline_info.pTessellationState = nullptr;
+ pipeline_info.pViewportState = &viewport_info;
+ pipeline_info.pRasterizationState = &rast_info;
+ pipeline_info.pMultisampleState = &multisample_info;
+ pipeline_info.pDepthStencilState = nullptr;
+ pipeline_info.pColorBlendState = &blend_info;
+ pipeline_info.pDynamicState = &dynamic_info;
+ pipeline_info.layout = pipeline_layout_;
+ pipeline_info.renderPass = render_pass_;
+ pipeline_info.subpass = 0;
+ vk::assert_success(vk::CreateGraphicsPipelines(dev_, VK_NULL_HANDLE, 1, &pipeline_info, nullptr, &pipeline_));
+}
+
+void Smoke::create_frame_data(int count)
+{
+ frame_data_.resize(count);
+
+ create_fences();
+ create_command_buffers();
+
+ if (!use_push_constants_) {
+ create_buffers();
+ create_buffer_memory();
+ create_descriptor_sets();
+ }
+
+ frame_data_index_ = 0;
+}
+
+void Smoke::destroy_frame_data()
+{
+ if (!use_push_constants_) {
+ vk::DestroyDescriptorPool(dev_, desc_pool_, nullptr);
+
+ for (auto cmd_pool : worker_cmd_pools_)
+ vk::DestroyCommandPool(dev_, cmd_pool, nullptr);
+ worker_cmd_pools_.clear();
+ vk::DestroyCommandPool(dev_, primary_cmd_pool_, nullptr);
+
+ vk::UnmapMemory(dev_, frame_data_mem_);
+ vk::FreeMemory(dev_, frame_data_mem_, nullptr);
+
+ for (auto &data : frame_data_)
+ vk::DestroyBuffer(dev_, data.buf, nullptr);
+ }
+
+ for (auto &data : frame_data_)
+ vk::DestroyFence(dev_, data.fence, nullptr);
+
+ frame_data_.clear();
+}
+
+void Smoke::create_fences()
+{
+ VkFenceCreateInfo fence_info = {};
+ fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
+ fence_info.flags = VK_FENCE_CREATE_SIGNALED_BIT;
+
+ for (auto &data : frame_data_)
+ vk::assert_success(vk::CreateFence(dev_, &fence_info, nullptr, &data.fence));
+}
+
+void Smoke::create_command_buffers()
+{
+ VkCommandPoolCreateInfo cmd_pool_info = {};
+ cmd_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
+ cmd_pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
+ cmd_pool_info.queueFamilyIndex = queue_family_;
+
+ VkCommandBufferAllocateInfo cmd_info = {};
+ cmd_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
+ cmd_info.commandBufferCount = static_cast<uint32_t>(frame_data_.size());
+
+ // create command pools and buffers
+ std::vector<VkCommandPool> cmd_pools(workers_.size() + 1, VK_NULL_HANDLE);
+ std::vector<std::vector<VkCommandBuffer>> cmds_vec(workers_.size() + 1,
+ std::vector<VkCommandBuffer>(frame_data_.size(), VK_NULL_HANDLE));
+ for (size_t i = 0; i < cmd_pools.size(); i++) {
+ auto &cmd_pool = cmd_pools[i];
+ auto &cmds = cmds_vec[i];
+
+ vk::assert_success(vk::CreateCommandPool(dev_, &cmd_pool_info,
+ nullptr, &cmd_pool));
+
+ cmd_info.commandPool = cmd_pool;
+ cmd_info.level = (cmd_pool == cmd_pools.back()) ?
+ VK_COMMAND_BUFFER_LEVEL_PRIMARY : VK_COMMAND_BUFFER_LEVEL_SECONDARY;
+
+ vk::assert_success(vk::AllocateCommandBuffers(dev_, &cmd_info, cmds.data()));
+ }
+
+ // update frame_data_
+ for (size_t i = 0; i < frame_data_.size(); i++) {
+ for (const auto &cmds : cmds_vec) {
+ if (cmds == cmds_vec.back()) {
+ frame_data_[i].primary_cmd = cmds[i];
+ } else {
+ frame_data_[i].worker_cmds.push_back(cmds[i]);
+ }
+ }
+ }
+
+ primary_cmd_pool_ = cmd_pools.back();
+ cmd_pools.pop_back();
+ worker_cmd_pools_ = cmd_pools;
+}
+
+void Smoke::create_buffers()
+{
+ VkDeviceSize object_data_size = sizeof(ShaderParamBlock);
+ // align object data to device limit
+ const VkDeviceSize &alignment =
+ physical_dev_props_.limits.minStorageBufferOffsetAlignment;
+ if (object_data_size % alignment)
+ object_data_size += alignment - (object_data_size % alignment);
+
+ // update simulation
+ sim_.set_frame_data_size(object_data_size);
+
+ VkBufferCreateInfo buf_info = {};
+ buf_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+ buf_info.size = object_data_size * sim_.objects().size();
+ buf_info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
+ buf_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+
+ for (auto &data : frame_data_)
+ vk::assert_success(vk::CreateBuffer(dev_, &buf_info, nullptr, &data.buf));
+}
+
+void Smoke::create_buffer_memory()
+{
+ VkMemoryRequirements mem_reqs;
+ vk::GetBufferMemoryRequirements(dev_, frame_data_[0].buf, &mem_reqs);
+
+ VkDeviceSize aligned_size = mem_reqs.size;
+ if (aligned_size % mem_reqs.alignment)
+ aligned_size += mem_reqs.alignment - (aligned_size % mem_reqs.alignment);
+
+ // allocate memory
+ VkMemoryAllocateInfo mem_info = {};
+ mem_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+ mem_info.allocationSize = aligned_size * (frame_data_.size() - 1) +
+ mem_reqs.size;
+
+ for (uint32_t idx = 0; idx < mem_flags_.size(); idx++) {
+ if ((mem_reqs.memoryTypeBits & (1 << idx)) &&
+ (mem_flags_[idx] & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) &&
+ (mem_flags_[idx] & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
+ // TODO is this guaranteed to exist?
+ mem_info.memoryTypeIndex = idx;
+ break;
+ }
+ }
+
+ vk::AllocateMemory(dev_, &mem_info, nullptr, &frame_data_mem_);
+
+ void *ptr;
+ vk::MapMemory(dev_, frame_data_mem_, 0, VK_WHOLE_SIZE, 0, &ptr);
+
+ VkDeviceSize offset = 0;
+ for (auto &data : frame_data_) {
+ vk::BindBufferMemory(dev_, data.buf, frame_data_mem_, offset);
+ data.base = reinterpret_cast<uint8_t *>(ptr) + offset;
+ offset += aligned_size;
+ }
+}
+
+void Smoke::create_descriptor_sets()
+{
+ VkDescriptorPoolSize desc_pool_size = {};
+ desc_pool_size.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
+ desc_pool_size.descriptorCount = frame_data_.size();
+
+ VkDescriptorPoolCreateInfo desc_pool_info = {};
+ desc_pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
+ desc_pool_info.maxSets = frame_data_.size();
+ desc_pool_info.poolSizeCount = 1;
+ desc_pool_info.pPoolSizes = &desc_pool_size;
+
+ // create descriptor pool
+ vk::assert_success(vk::CreateDescriptorPool(dev_, &desc_pool_info,
+ nullptr, &desc_pool_));
+
+ std::vector<VkDescriptorSetLayout> set_layouts(frame_data_.size(), desc_set_layout_);
+ VkDescriptorSetAllocateInfo set_info = {};
+ set_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
+ set_info.descriptorPool = desc_pool_;
+ set_info.descriptorSetCount = static_cast<uint32_t>(set_layouts.size());
+ set_info.pSetLayouts = set_layouts.data();
+
+ // create descriptor sets
+ std::vector<VkDescriptorSet> desc_sets(frame_data_.size(), VK_NULL_HANDLE);
+ vk::assert_success(vk::AllocateDescriptorSets(dev_, &set_info, desc_sets.data()));
+
+ std::vector<VkDescriptorBufferInfo> desc_bufs(frame_data_.size());
+ std::vector<VkWriteDescriptorSet> desc_writes(frame_data_.size());
+
+ for (size_t i = 0; i < frame_data_.size(); i++) {
+ auto &data = frame_data_[i];
+
+ data.desc_set = desc_sets[i];
+
+ VkDescriptorBufferInfo desc_buf = {};
+ desc_buf.buffer = data.buf;
+ desc_buf.offset = 0;
+ desc_buf.range = VK_WHOLE_SIZE;
+ desc_bufs[i] = desc_buf;
+
+ VkWriteDescriptorSet desc_write = {};
+ desc_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ desc_write.dstSet = data.desc_set;
+ desc_write.dstBinding = 0;
+ desc_write.dstArrayElement = 0;
+ desc_write.descriptorCount = 1;
+ desc_write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
+ desc_write.pBufferInfo = &desc_bufs[i];
+ desc_writes[i] = desc_write;
+ }
+
+ vk::UpdateDescriptorSets(dev_,
+ static_cast<uint32_t>(desc_writes.size()),
+ desc_writes.data(), 0, nullptr);
+}
+
+void Smoke::attach_swapchain()
+{
+ const Shell::Context &ctx = shell_->context();
+
+ prepare_viewport(ctx.extent);
+ prepare_framebuffers(ctx.swapchain);
+
+ update_camera();
+}
+
+void Smoke::detach_swapchain()
+{
+ for (auto fb : framebuffers_)
+ vk::DestroyFramebuffer(dev_, fb, nullptr);
+ for (auto view : image_views_)
+ vk::DestroyImageView(dev_, view, nullptr);
+
+ framebuffers_.clear();
+ image_views_.clear();
+ images_.clear();
+}
+
+void Smoke::prepare_viewport(const VkExtent2D &extent)
+{
+ extent_ = extent;
+
+ viewport_.x = 0.0f;
+ viewport_.y = 0.0f;
+ viewport_.width = static_cast<float>(extent.width);
+ viewport_.height = static_cast<float>(extent.height);
+ viewport_.minDepth = 0.0f;
+ viewport_.maxDepth = 1.0f;
+
+ scissor_.offset = { 0, 0 };
+ scissor_.extent = extent_;
+}
+
+void Smoke::prepare_framebuffers(VkSwapchainKHR swapchain)
+{
+ // get swapchain images
+ vk::get(dev_, swapchain, images_);
+
+ assert(framebuffers_.empty());
+ image_views_.reserve(images_.size());
+ framebuffers_.reserve(images_.size());
+ for (auto img : images_) {
+ VkImageViewCreateInfo view_info = {};
+ view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+ view_info.image = img;
+ view_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
+ view_info.format = format_;
+ view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ view_info.subresourceRange.levelCount = 1;
+ view_info.subresourceRange.layerCount = 1;
+
+ VkImageView view;
+ vk::assert_success(vk::CreateImageView(dev_, &view_info, nullptr, &view));
+ image_views_.push_back(view);
+
+ VkFramebufferCreateInfo fb_info = {};
+ fb_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
+ fb_info.renderPass = render_pass_;
+ fb_info.attachmentCount = 1;
+ fb_info.pAttachments = &view;
+ fb_info.width = extent_.width;
+ fb_info.height = extent_.height;
+ fb_info.layers = 1;
+
+ VkFramebuffer fb;
+ vk::assert_success(vk::CreateFramebuffer(dev_, &fb_info, nullptr, &fb));
+ framebuffers_.push_back(fb);
+ }
+}
+
+void Smoke::update_camera()
+{
+ const glm::vec3 center(0.0f);
+ const glm::vec3 up(0.f, 0.0f, 1.0f);
+ const glm::mat4 view = glm::lookAt(camera_.eye_pos, center, up);
+
+ float aspect = static_cast<float>(extent_.width) / static_cast<float>(extent_.height);
+ const glm::mat4 projection = glm::perspective(0.4f, aspect, 0.1f, 100.0f);
+
+ // Vulkan clip space has inverted Y and half Z.
+ const glm::mat4 clip(1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, -1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.5f, 0.0f,
+ 0.0f, 0.0f, 0.5f, 1.0f);
+
+ camera_.view_projection = clip * projection * view;
+}
+
+void Smoke::draw_object(const Simulation::Object &obj, FrameData &data, VkCommandBuffer cmd) const
+{
+ if (use_push_constants_) {
+ ShaderParamBlock params;
+ memcpy(params.light_pos, glm::value_ptr(obj.light_pos), sizeof(obj.light_pos));
+ memcpy(params.light_color, glm::value_ptr(obj.light_color), sizeof(obj.light_color));
+ memcpy(params.model, glm::value_ptr(obj.model), sizeof(obj.model));
+ memcpy(params.view_projection, glm::value_ptr(camera_.view_projection), sizeof(camera_.view_projection));
+
+ vk::CmdPushConstants(cmd, pipeline_layout_, VK_SHADER_STAGE_VERTEX_BIT,
+ 0, sizeof(params), &params);
+ } else {
+ ShaderParamBlock *params =
+ reinterpret_cast<ShaderParamBlock *>(data.base + obj.frame_data_offset);
+ memcpy(params->light_pos, glm::value_ptr(obj.light_pos), sizeof(obj.light_pos));
+ memcpy(params->light_color, glm::value_ptr(obj.light_color), sizeof(obj.light_color));
+ memcpy(params->model, glm::value_ptr(obj.model), sizeof(obj.model));
+ memcpy(params->view_projection, glm::value_ptr(camera_.view_projection), sizeof(camera_.view_projection));
+
+ vk::CmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
+ pipeline_layout_, 0, 1, &data.desc_set, 1, &obj.frame_data_offset);
+ }
+
+ meshes_->cmd_draw(cmd, obj.mesh);
+}
+
+void Smoke::update_simulation(const Worker &worker)
+{
+ sim_.update(worker.tick_interval_, worker.object_begin_, worker.object_end_);
+}
+
+void Smoke::draw_objects(Worker &worker)
+{
+ auto &data = frame_data_[frame_data_index_];
+ auto cmd = data.worker_cmds[worker.index_];
+
+ VkCommandBufferInheritanceInfo inherit_info = {};
+ inherit_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
+ inherit_info.renderPass = render_pass_;
+ inherit_info.framebuffer = worker.fb_;
+
+ VkCommandBufferBeginInfo begin_info = {};
+ begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ begin_info.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
+ begin_info.pInheritanceInfo = &inherit_info;
+
+ vk::BeginCommandBuffer(cmd, &begin_info);
+
+ vk::CmdSetViewport(cmd, 0, 1, &viewport_);
+ vk::CmdSetScissor(cmd, 0, 1, &scissor_);
+
+ vk::CmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_);
+
+ meshes_->cmd_bind_buffers(cmd);
+
+ for (int i = worker.object_begin_; i < worker.object_end_; i++) {
+ auto &obj = sim_.objects()[i];
+
+ draw_object(obj, data, cmd);
+ }
+
+ vk::EndCommandBuffer(cmd);
+}
+
+void Smoke::on_key(Key key)
+{
+ switch (key) {
+ case KEY_SHUTDOWN:
+ case KEY_ESC:
+ shell_->quit();
+ break;
+ case KEY_UP:
+ camera_.eye_pos -= glm::vec3(0.05f);
+ update_camera();
+ break;
+ case KEY_DOWN:
+ camera_.eye_pos += glm::vec3(0.05f);
+ update_camera();
+ break;
+ case KEY_SPACE:
+ sim_paused_ = !sim_paused_;
+ break;
+ default:
+ break;
+ }
+}
+
+void Smoke::on_tick()
+{
+ if (sim_paused_)
+ return;
+
+ for (auto &worker : workers_)
+ worker->update_simulation();
+}
+
+void Smoke::on_frame(float frame_pred)
+{
+ auto &data = frame_data_[frame_data_index_];
+
+ // wait for the last submission since we reuse frame data
+ vk::assert_success(vk::WaitForFences(dev_, 1, &data.fence, true, UINT64_MAX));
+ vk::assert_success(vk::ResetFences(dev_, 1, &data.fence));
+
+ const Shell::BackBuffer &back = shell_->context().acquired_back_buffer;
+
+ // ignore frame_pred
+ for (auto &worker : workers_)
+ worker->draw_objects(framebuffers_[back.image_index]);
+
+ VkResult res = vk::BeginCommandBuffer(data.primary_cmd, &primary_cmd_begin_info_);
+
+ VkBufferMemoryBarrier buf_barrier = {};
+ buf_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
+ buf_barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
+ buf_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
+ buf_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ buf_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ buf_barrier.buffer = data.buf;
+ buf_barrier.offset = 0;
+ buf_barrier.size = VK_WHOLE_SIZE;
+ vk::CmdPipelineBarrier(data.primary_cmd,
+ VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
+ 0, 0, nullptr, 1, &buf_barrier, 0, nullptr);
+
+ render_pass_begin_info_.framebuffer = framebuffers_[back.image_index];
+ render_pass_begin_info_.renderArea.extent = extent_;
+ vk::CmdBeginRenderPass(data.primary_cmd, &render_pass_begin_info_,
+ VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
+
+ // record render pass commands
+ for (auto &worker : workers_)
+ worker->wait_idle();
+ vk::CmdExecuteCommands(data.primary_cmd,
+ static_cast<uint32_t>(data.worker_cmds.size()),
+ data.worker_cmds.data());
+
+ vk::CmdEndRenderPass(data.primary_cmd);
+ vk::EndCommandBuffer(data.primary_cmd);
+
+ // wait for the image to be owned and signal for render completion
+ primary_cmd_submit_info_.pWaitSemaphores = &back.acquire_semaphore;
+ primary_cmd_submit_info_.pCommandBuffers = &data.primary_cmd;
+ primary_cmd_submit_info_.pSignalSemaphores = &back.render_semaphore;
+
+ res = vk::QueueSubmit(queue_, 1, &primary_cmd_submit_info_, data.fence);
+
+ frame_data_index_ = (frame_data_index_ + 1) % frame_data_.size();
+
+ (void) res;
+}
+
+Smoke::Worker::Worker(Smoke &smoke, int index, int object_begin, int object_end)
+ : smoke_(smoke), index_(index),
+ object_begin_(object_begin), object_end_(object_end),
+ tick_interval_(1.0f / smoke.settings_.ticks_per_second), state_(INIT)
+{
+}
+
+void Smoke::Worker::start()
+{
+ state_ = IDLE;
+ thread_ = std::thread(Smoke::Worker::thread_loop, this);
+}
+
+void Smoke::Worker::stop()
+{
+ {
+ std::lock_guard<std::mutex> lock(mutex_);
+ state_ = INIT;
+ }
+ state_cv_.notify_one();
+
+ thread_.join();
+}
+
+void Smoke::Worker::update_simulation()
+{
+ {
+ std::lock_guard<std::mutex> lock(mutex_);
+ bool started = (state_ != INIT);
+
+ state_ = STEP;
+
+ // step directly
+ if (!started) {
+ smoke_.update_simulation(*this);
+ state_ = INIT;
+ }
+ }
+ state_cv_.notify_one();
+}
+
+void Smoke::Worker::draw_objects(VkFramebuffer fb)
+{
+ // wait for step_objects first
+ wait_idle();
+
+ {
+ std::lock_guard<std::mutex> lock(mutex_);
+ bool started = (state_ != INIT);
+
+ fb_ = fb;
+ state_ = DRAW;
+
+ // render directly
+ if (!started) {
+ smoke_.draw_objects(*this);
+ state_ = INIT;
+ }
+ }
+ state_cv_.notify_one();
+}
+
+void Smoke::Worker::wait_idle()
+{
+ std::unique_lock<std::mutex> lock(mutex_);
+ bool started = (state_ != INIT);
+
+ if (started)
+ state_cv_.wait(lock, [this] { return (state_ == IDLE); });
+}
+
+void Smoke::Worker::update_loop()
+{
+ while (true) {
+ std::unique_lock<std::mutex> lock(mutex_);
+
+ state_cv_.wait(lock, [this] { return (state_ != IDLE); });
+ if (state_ == INIT)
+ break;
+
+ assert(state_ == STEP || state_ == DRAW);
+ if (state_ == STEP)
+ smoke_.update_simulation(*this);
+ else
+ smoke_.draw_objects(*this);
+
+ state_ = IDLE;
+ lock.unlock();
+ state_cv_.notify_one();
+ }
+}
diff --git a/demos/smoke/Smoke.frag b/demos/smoke/Smoke.frag
new file mode 100644
index 00000000..e07a46f5
--- /dev/null
+++ b/demos/smoke/Smoke.frag
@@ -0,0 +1,12 @@
+#version 310 es
+
+precision highp float;
+
+in vec3 color;
+
+layout(location = 0) out vec4 fragcolor;
+
+void main()
+{
+ fragcolor = vec4(color, 0.5);
+}
diff --git a/demos/smoke/Smoke.h b/demos/smoke/Smoke.h
new file mode 100644
index 00000000..44bd4812
--- /dev/null
+++ b/demos/smoke/Smoke.h
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2016 Google, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef SMOKE_H
+#define SMOKE_H
+
+#include <condition_variable>
+#include <memory>
+#include <mutex>
+#include <string>
+#include <thread>
+#include <vector>
+
+#include <vulkan/vulkan.h>
+#include <glm/glm.hpp>
+
+#include "Simulation.h"
+#include "Game.h"
+
+class Meshes;
+
+class Smoke : public Game {
+public:
+ Smoke(const std::vector<std::string> &args);
+ ~Smoke();
+
+ void attach_shell(Shell &sh);
+ void detach_shell();
+
+ void attach_swapchain();
+ void detach_swapchain();
+
+ void on_key(Key key);
+ void on_tick();
+
+ void on_frame(float frame_pred);
+
+private:
+ class Worker {
+ public:
+ Worker(Smoke &smoke, int index, int object_begin, int object_end);
+
+ void start();
+ void stop();
+ void update_simulation();
+ void draw_objects(VkFramebuffer fb);
+ void wait_idle();
+
+ Smoke &smoke_;
+
+ const int index_;
+ const int object_begin_;
+ const int object_end_;
+
+ const float tick_interval_;
+
+ VkFramebuffer fb_;
+
+ private:
+ enum State {
+ INIT,
+ IDLE,
+ STEP,
+ DRAW,
+ };
+
+ void update_loop();
+
+ static void thread_loop(Worker *worker) { worker->update_loop(); }
+
+ std::thread thread_;
+ std::mutex mutex_;
+ std::condition_variable state_cv_;
+ State state_;
+ };
+
+ struct Camera {
+ glm::vec3 eye_pos;
+ glm::mat4 view_projection;
+
+ Camera(float eye) : eye_pos(eye) {}
+ };
+
+ struct FrameData {
+ // signaled when this struct is ready for reuse
+ VkFence fence;
+
+ VkCommandBuffer primary_cmd;
+ std::vector<VkCommandBuffer> worker_cmds;
+
+ VkBuffer buf;
+ uint8_t *base;
+ VkDescriptorSet desc_set;
+ };
+
+ // called by the constructor
+ void init_workers();
+
+ bool multithread_;
+ bool use_push_constants_;
+
+ // called mostly by on_key
+ void update_camera();
+
+ bool sim_paused_;
+ Simulation sim_;
+ Camera camera_;
+
+ std::vector<std::unique_ptr<Worker>> workers_;
+
+ // called by attach_shell
+ void create_render_pass();
+ void create_shader_modules();
+ void create_descriptor_set_layout();
+ void create_pipeline_layout();
+ void create_pipeline();
+
+ void create_frame_data(int count);
+ void destroy_frame_data();
+ void create_fences();
+ void create_command_buffers();
+ void create_buffers();
+ void create_buffer_memory();
+ void create_descriptor_sets();
+
+ VkPhysicalDevice physical_dev_;
+ VkDevice dev_;
+ VkQueue queue_;
+ uint32_t queue_family_;
+ VkFormat format_;
+
+ VkPhysicalDeviceProperties physical_dev_props_;
+ std::vector<VkMemoryPropertyFlags> mem_flags_;
+
+ const Meshes *meshes_;
+
+ VkRenderPass render_pass_;
+ VkShaderModule vs_;
+ VkShaderModule fs_;
+ VkDescriptorSetLayout desc_set_layout_;
+ VkPipelineLayout pipeline_layout_;
+ VkPipeline pipeline_;
+
+ VkCommandPool primary_cmd_pool_;
+ std::vector<VkCommandPool> worker_cmd_pools_;
+ VkDescriptorPool desc_pool_;
+ VkDeviceMemory frame_data_mem_;
+ std::vector<FrameData> frame_data_;
+ int frame_data_index_;
+
+ VkClearValue render_pass_clear_value_;
+ VkRenderPassBeginInfo render_pass_begin_info_;
+
+ VkCommandBufferBeginInfo primary_cmd_begin_info_;
+ VkPipelineStageFlags primary_cmd_submit_wait_stages_;
+ VkSubmitInfo primary_cmd_submit_info_;
+
+ // called by attach_swapchain
+ void prepare_viewport(const VkExtent2D &extent);
+ void prepare_framebuffers(VkSwapchainKHR swapchain);
+
+ VkExtent2D extent_;
+ VkViewport viewport_;
+ VkRect2D scissor_;
+
+ std::vector<VkImage> images_;
+ std::vector<VkImageView> image_views_;
+ std::vector<VkFramebuffer> framebuffers_;
+
+ // called by workers
+ void update_simulation(const Worker &worker);
+ void draw_object(const Simulation::Object &obj, FrameData &data, VkCommandBuffer cmd) const;
+ void draw_objects(Worker &worker);
+};
+
+#endif // HOLOGRAM_H
diff --git a/demos/smoke/Smoke.push_constant.vert b/demos/smoke/Smoke.push_constant.vert
new file mode 100644
index 00000000..e2357fb0
--- /dev/null
+++ b/demos/smoke/Smoke.push_constant.vert
@@ -0,0 +1,27 @@
+#version 310 es
+
+layout(location = 0) in vec3 in_pos;
+layout(location = 1) in vec3 in_normal;
+
+layout(std140, push_constant) uniform param_block {
+ vec3 light_pos;
+ vec3 light_color;
+ mat4 model;
+ mat4 view_projection;
+} params;
+
+out vec3 color;
+
+void main()
+{
+ vec3 world_light = vec3(params.model * vec4(params.light_pos, 1.0));
+ vec3 world_pos = vec3(params.model * vec4(in_pos, 1.0));
+ vec3 world_normal = mat3(params.model) * in_normal;
+
+ vec3 light_dir = world_light - world_pos;
+ float brightness = dot(light_dir, world_normal) / length(light_dir) / length(world_normal);
+ brightness = abs(brightness);
+
+ gl_Position = params.view_projection * vec4(world_pos, 1.0);
+ color = params.light_color * brightness;
+}
diff --git a/demos/smoke/Smoke.vert b/demos/smoke/Smoke.vert
new file mode 100644
index 00000000..60bda60b
--- /dev/null
+++ b/demos/smoke/Smoke.vert
@@ -0,0 +1,27 @@
+#version 310 es
+
+layout(location = 0) in vec3 in_pos;
+layout(location = 1) in vec3 in_normal;
+
+layout(std140, set = 0, binding = 0) readonly buffer param_block {
+ vec3 light_pos;
+ vec3 light_color;
+ mat4 model;
+ mat4 view_projection;
+} params;
+
+out vec3 color;
+
+void main()
+{
+ vec3 world_light = vec3(params.model * vec4(params.light_pos, 1.0));
+ vec3 world_pos = vec3(params.model * vec4(in_pos, 1.0));
+ vec3 world_normal = mat3(params.model) * in_normal;
+
+ vec3 light_dir = world_light - world_pos;
+ float brightness = dot(light_dir, world_normal) / length(light_dir) / length(world_normal);
+ brightness = abs(brightness);
+
+ gl_Position = params.view_projection * vec4(world_pos, 1.0);
+ color = params.light_color * brightness;
+}
diff --git a/demos/smoke/android/build-and-install b/demos/smoke/android/build-and-install
new file mode 100755
index 00000000..cbdaf0ac
--- /dev/null
+++ b/demos/smoke/android/build-and-install
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+set -e
+
+SDK_DIR="$HOME/android/android-sdk-linux"
+NDK_DIR="$HOME/android/android-ndk-r10e"
+
+generate_local_properties() {
+ : > local.properties
+ echo "sdk.dir=${SDK_DIR}" >> local.properties
+ echo "ndk.dir=${NDK_DIR}" >> local.properties
+}
+
+build() {
+ ./gradlew build
+}
+
+install() {
+ adb uninstall com.example.Smoke
+ adb install build/outputs/apk/android-fat-debug.apk
+}
+
+run() {
+ adb shell am start com.example.Smoke/android.app.NativeActivity
+}
+
+generate_local_properties
+build
+install
+#run
diff --git a/demos/smoke/android/build.gradle b/demos/smoke/android/build.gradle
new file mode 100644
index 00000000..d04ba8ee
--- /dev/null
+++ b/demos/smoke/android/build.gradle
@@ -0,0 +1,87 @@
+buildscript {
+ repositories {
+ jcenter()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle-experimental:0.6.0-alpha3'
+ }
+}
+
+apply plugin: 'com.android.model.application'
+
+def demosDir = "../.."
+def smokeDir = "${demosDir}/demos/Smoke"
+def glmDir = "${demosDir}/../libs"
+def vulkanDir = "${demosDir}/../Vulkan-Docs/src"
+
+Properties properties = new Properties()
+properties.load(project.rootProject.file('local.properties').newDataInputStream())
+def ndkDir = properties.getProperty('ndk.dir')
+
+model {
+ android {
+ compileSdkVersion = 23
+ buildToolsVersion = "23.0.2"
+
+ defaultConfig.with {
+ applicationId = "com.example.Smoke"
+ minSdkVersion.apiLevel = 22
+ targetSdkVersion.apiLevel = 22
+ versionCode = 1
+ versionName = "0.1"
+ }
+ }
+
+ android.ndk {
+ moduleName = "Smoke"
+ toolchain = "clang"
+ stl = "c++_static"
+
+ cppFlags.addAll(["-std=c++11", "-fexceptions"])
+ cppFlags.addAll(["-Wall", "-Wextra", "-Wno-unused-parameter"])
+
+ cppFlags.addAll([
+ "-DVK_NO_PROTOTYPES",
+ "-DVK_USE_PLATFORM_ANDROID_KHR",
+ "-DGLM_FORCE_RADIANS",
+ ])
+
+ cppFlags.addAll([
+ "-I${file("${ndkDir}/sources/android/native_app_glue")}".toString(),
+ "-I${file("${vulkanDir}")}".toString(),
+ "-I${file("${glmDir}")}".toString(),
+ "-I${file("src/main/jni")}".toString(),
+ ])
+
+ ldLibs.addAll(["android", "log", "dl"])
+ }
+
+ android.sources {
+ main {
+ jni {
+ source {
+ srcDir "${ndkDir}/sources/android/native_app_glue"
+ srcDir "${smokeDir}"
+ exclude 'ShellXcb.cpp'
+ exclude 'ShellWin32.cpp'
+ }
+ }
+ }
+ }
+
+ android.buildTypes {
+ release {
+ ndk.with {
+ debuggable = true
+ }
+ }
+ }
+
+ android.productFlavors {
+ create ("fat") {
+ ndk.abiFilters.add("armeabi-v7a")
+ ndk.abiFilters.add("x86")
+ }
+ }
+}
diff --git a/demos/smoke/android/gradle/wrapper/gradle-wrapper.jar b/demos/smoke/android/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 00000000..13372aef
--- /dev/null
+++ b/demos/smoke/android/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/demos/smoke/android/gradle/wrapper/gradle-wrapper.properties b/demos/smoke/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000..0fa19137
--- /dev/null
+++ b/demos/smoke/android/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Jan 27 08:20:52 CST 2016
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.9-bin.zip
diff --git a/demos/smoke/android/gradlew b/demos/smoke/android/gradlew
new file mode 100755
index 00000000..9d82f789
--- /dev/null
+++ b/demos/smoke/android/gradlew
@@ -0,0 +1,160 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/demos/smoke/android/gradlew.bat b/demos/smoke/android/gradlew.bat
new file mode 100644
index 00000000..aec99730
--- /dev/null
+++ b/demos/smoke/android/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/demos/smoke/android/src/main/AndroidManifest.xml b/demos/smoke/android/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..c68af879
--- /dev/null
+++ b/demos/smoke/android/src/main/AndroidManifest.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.Smoke">
+
+ <application android:label="@string/app_name"
+ android:hasCode="false"
+ android:allowBackup="false">
+ <activity android:name="android.app.NativeActivity"
+ android:label="@string/app_name">
+
+ <meta-data android:name="android.app.lib_name"
+ android:value="Smoke"/>
+
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/demos/smoke/android/src/main/jni/Smoke.frag.h b/demos/smoke/android/src/main/jni/Smoke.frag.h
new file mode 100644
index 00000000..5149ad6b
--- /dev/null
+++ b/demos/smoke/android/src/main/jni/Smoke.frag.h
@@ -0,0 +1,78 @@
+#include <stdint.h>
+
+#if 0
+/usr/local/google/home/olv/khronos/VulkanSamples/Demos/Hologram/Hologram.frag
+Warning, version 310 is not yet complete; most version-specific features are present, but some are missing.
+
+
+Linked fragment stage:
+
+
+// Module Version 10000
+// Generated by (magic number): 80001
+// Id's are bound by 19
+
+ Capability Shader
+ 1: ExtInstImport "GLSL.std.450"
+ MemoryModel Logical GLSL450
+ EntryPoint Fragment 4 "main" 9 12
+ ExecutionMode 4 OriginLowerLeft
+ Source ESSL 310
+ Name 4 "main"
+ Name 9 "fragcolor"
+ Name 12 "color"
+ Decorate 9(fragcolor) Location 0
+ 2: TypeVoid
+ 3: TypeFunction 2
+ 6: TypeFloat 32
+ 7: TypeVector 6(float) 4
+ 8: TypePointer Output 7(fvec4)
+ 9(fragcolor): 8(ptr) Variable Output
+ 10: TypeVector 6(float) 3
+ 11: TypePointer Input 10(fvec3)
+ 12(color): 11(ptr) Variable Input
+ 14: 6(float) Constant 1056964608
+ 4(main): 2 Function None 3
+ 5: Label
+ 13: 10(fvec3) Load 12(color)
+ 15: 6(float) CompositeExtract 13 0
+ 16: 6(float) CompositeExtract 13 1
+ 17: 6(float) CompositeExtract 13 2
+ 18: 7(fvec4) CompositeConstruct 15 16 17 14
+ Store 9(fragcolor) 18
+ Return
+ FunctionEnd
+#endif
+
+static const uint32_t Smoke_frag[120] = {
+ 0x07230203, 0x00010000, 0x00080001, 0x00000013,
+ 0x00000000, 0x00020011, 0x00000001, 0x0006000b,
+ 0x00000001, 0x4c534c47, 0x6474732e, 0x3035342e,
+ 0x00000000, 0x0003000e, 0x00000000, 0x00000001,
+ 0x0007000f, 0x00000004, 0x00000004, 0x6e69616d,
+ 0x00000000, 0x00000009, 0x0000000c, 0x00030010,
+ 0x00000004, 0x00000008, 0x00030003, 0x00000001,
+ 0x00000136, 0x00040005, 0x00000004, 0x6e69616d,
+ 0x00000000, 0x00050005, 0x00000009, 0x67617266,
+ 0x6f6c6f63, 0x00000072, 0x00040005, 0x0000000c,
+ 0x6f6c6f63, 0x00000072, 0x00040047, 0x00000009,
+ 0x0000001e, 0x00000000, 0x00020013, 0x00000002,
+ 0x00030021, 0x00000003, 0x00000002, 0x00030016,
+ 0x00000006, 0x00000020, 0x00040017, 0x00000007,
+ 0x00000006, 0x00000004, 0x00040020, 0x00000008,
+ 0x00000003, 0x00000007, 0x0004003b, 0x00000008,
+ 0x00000009, 0x00000003, 0x00040017, 0x0000000a,
+ 0x00000006, 0x00000003, 0x00040020, 0x0000000b,
+ 0x00000001, 0x0000000a, 0x0004003b, 0x0000000b,
+ 0x0000000c, 0x00000001, 0x0004002b, 0x00000006,
+ 0x0000000e, 0x3f000000, 0x00050036, 0x00000002,
+ 0x00000004, 0x00000000, 0x00000003, 0x000200f8,
+ 0x00000005, 0x0004003d, 0x0000000a, 0x0000000d,
+ 0x0000000c, 0x00050051, 0x00000006, 0x0000000f,
+ 0x0000000d, 0x00000000, 0x00050051, 0x00000006,
+ 0x00000010, 0x0000000d, 0x00000001, 0x00050051,
+ 0x00000006, 0x00000011, 0x0000000d, 0x00000002,
+ 0x00070050, 0x00000007, 0x00000012, 0x0000000f,
+ 0x00000010, 0x00000011, 0x0000000e, 0x0003003e,
+ 0x00000009, 0x00000012, 0x000100fd, 0x00010038,
+};
diff --git a/demos/smoke/android/src/main/jni/Smoke.push_constant.vert.h b/demos/smoke/android/src/main/jni/Smoke.push_constant.vert.h
new file mode 100644
index 00000000..db571a02
--- /dev/null
+++ b/demos/smoke/android/src/main/jni/Smoke.push_constant.vert.h
@@ -0,0 +1,352 @@
+#include <stdint.h>
+
+#if 0
+/usr/local/google/home/olv/khronos/VulkanSamples/Demos/Hologram/Hologram.push_constant.vert
+Warning, version 310 is not yet complete; most version-specific features are present, but some are missing.
+
+
+Linked vertex stage:
+
+
+// Module Version 10000
+// Generated by (magic number): 80001
+// Id's are bound by 108
+
+ Capability Shader
+ 1: ExtInstImport "GLSL.std.450"
+ MemoryModel Logical GLSL450
+ EntryPoint Vertex 4 "main" 38 67 89 102
+ Source ESSL 310
+ Name 4 "main"
+ Name 9 "world_light"
+ Name 12 "param_block"
+ MemberName 12(param_block) 0 "light_pos"
+ MemberName 12(param_block) 1 "light_color"
+ MemberName 12(param_block) 2 "model"
+ MemberName 12(param_block) 3 "view_projection"
+ Name 14 "params"
+ Name 34 "world_pos"
+ Name 38 "in_pos"
+ Name 49 "world_normal"
+ Name 67 "in_normal"
+ Name 70 "light_dir"
+ Name 75 "brightness"
+ Name 87 "gl_PerVertex"
+ MemberName 87(gl_PerVertex) 0 "gl_Position"
+ MemberName 87(gl_PerVertex) 1 "gl_PointSize"
+ Name 89 ""
+ Name 102 "color"
+ MemberDecorate 12(param_block) 0 Offset 0
+ MemberDecorate 12(param_block) 1 Offset 16
+ MemberDecorate 12(param_block) 2 ColMajor
+ MemberDecorate 12(param_block) 2 Offset 32
+ MemberDecorate 12(param_block) 2 MatrixStride 16
+ MemberDecorate 12(param_block) 3 ColMajor
+ MemberDecorate 12(param_block) 3 Offset 96
+ MemberDecorate 12(param_block) 3 MatrixStride 16
+ Decorate 12(param_block) Block
+ Decorate 14(params) DescriptorSet 0
+ Decorate 38(in_pos) Location 0
+ Decorate 67(in_normal) Location 1
+ MemberDecorate 87(gl_PerVertex) 0 BuiltIn Position
+ MemberDecorate 87(gl_PerVertex) 1 BuiltIn PointSize
+ Decorate 87(gl_PerVertex) Block
+ 2: TypeVoid
+ 3: TypeFunction 2
+ 6: TypeFloat 32
+ 7: TypeVector 6(float) 3
+ 8: TypePointer Function 7(fvec3)
+ 10: TypeVector 6(float) 4
+ 11: TypeMatrix 10(fvec4) 4
+ 12(param_block): TypeStruct 7(fvec3) 7(fvec3) 11 11
+ 13: TypePointer PushConstant 12(param_block)
+ 14(params): 13(ptr) Variable PushConstant
+ 15: TypeInt 32 1
+ 16: 15(int) Constant 2
+ 17: TypePointer PushConstant 11
+ 20: 15(int) Constant 0
+ 21: TypePointer PushConstant 7(fvec3)
+ 24: 6(float) Constant 1065353216
+ 37: TypePointer Input 7(fvec3)
+ 38(in_pos): 37(ptr) Variable Input
+ 52: TypeMatrix 7(fvec3) 3
+ 53: 6(float) Constant 0
+ 67(in_normal): 37(ptr) Variable Input
+ 74: TypePointer Function 6(float)
+87(gl_PerVertex): TypeStruct 10(fvec4) 6(float)
+ 88: TypePointer Output 87(gl_PerVertex)
+ 89: 88(ptr) Variable Output
+ 90: 15(int) Constant 3
+ 99: TypePointer Output 10(fvec4)
+ 101: TypePointer Output 7(fvec3)
+ 102(color): 101(ptr) Variable Output
+ 103: 15(int) Constant 1
+ 4(main): 2 Function None 3
+ 5: Label
+ 9(world_light): 8(ptr) Variable Function
+ 34(world_pos): 8(ptr) Variable Function
+49(world_normal): 8(ptr) Variable Function
+ 70(light_dir): 8(ptr) Variable Function
+ 75(brightness): 74(ptr) Variable Function
+ 18: 17(ptr) AccessChain 14(params) 16
+ 19: 11 Load 18
+ 22: 21(ptr) AccessChain 14(params) 20
+ 23: 7(fvec3) Load 22
+ 25: 6(float) CompositeExtract 23 0
+ 26: 6(float) CompositeExtract 23 1
+ 27: 6(float) CompositeExtract 23 2
+ 28: 10(fvec4) CompositeConstruct 25 26 27 24
+ 29: 10(fvec4) MatrixTimesVector 19 28
+ 30: 6(float) CompositeExtract 29 0
+ 31: 6(float) CompositeExtract 29 1
+ 32: 6(float) CompositeExtract 29 2
+ 33: 7(fvec3) CompositeConstruct 30 31 32
+ Store 9(world_light) 33
+ 35: 17(ptr) AccessChain 14(params) 16
+ 36: 11 Load 35
+ 39: 7(fvec3) Load 38(in_pos)
+ 40: 6(float) CompositeExtract 39 0
+ 41: 6(float) CompositeExtract 39 1
+ 42: 6(float) CompositeExtract 39 2
+ 43: 10(fvec4) CompositeConstruct 40 41 42 24
+ 44: 10(fvec4) MatrixTimesVector 36 43
+ 45: 6(float) CompositeExtract 44 0
+ 46: 6(float) CompositeExtract 44 1
+ 47: 6(float) CompositeExtract 44 2
+ 48: 7(fvec3) CompositeConstruct 45 46 47
+ Store 34(world_pos) 48
+ 50: 17(ptr) AccessChain 14(params) 16
+ 51: 11 Load 50
+ 54: 6(float) CompositeExtract 51 0 0
+ 55: 6(float) CompositeExtract 51 0 1
+ 56: 6(float) CompositeExtract 51 0 2
+ 57: 6(float) CompositeExtract 51 1 0
+ 58: 6(float) CompositeExtract 51 1 1
+ 59: 6(float) CompositeExtract 51 1 2
+ 60: 6(float) CompositeExtract 51 2 0
+ 61: 6(float) CompositeExtract 51 2 1
+ 62: 6(float) CompositeExtract 51 2 2
+ 63: 7(fvec3) CompositeConstruct 54 55 56
+ 64: 7(fvec3) CompositeConstruct 57 58 59
+ 65: 7(fvec3) CompositeConstruct 60 61 62
+ 66: 52 CompositeConstruct 63 64 65
+ 68: 7(fvec3) Load 67(in_normal)
+ 69: 7(fvec3) MatrixTimesVector 66 68
+ Store 49(world_normal) 69
+ 71: 7(fvec3) Load 9(world_light)
+ 72: 7(fvec3) Load 34(world_pos)
+ 73: 7(fvec3) FSub 71 72
+ Store 70(light_dir) 73
+ 76: 7(fvec3) Load 70(light_dir)
+ 77: 7(fvec3) Load 49(world_normal)
+ 78: 6(float) Dot 76 77
+ 79: 7(fvec3) Load 70(light_dir)
+ 80: 6(float) ExtInst 1(GLSL.std.450) 66(Length) 79
+ 81: 6(float) FDiv 78 80
+ 82: 7(fvec3) Load 49(world_normal)
+ 83: 6(float) ExtInst 1(GLSL.std.450) 66(Length) 82
+ 84: 6(float) FDiv 81 83
+ Store 75(brightness) 84
+ 85: 6(float) Load 75(brightness)
+ 86: 6(float) ExtInst 1(GLSL.std.450) 4(FAbs) 85
+ Store 75(brightness) 86
+ 91: 17(ptr) AccessChain 14(params) 90
+ 92: 11 Load 91
+ 93: 7(fvec3) Load 34(world_pos)
+ 94: 6(float) CompositeExtract 93 0
+ 95: 6(float) CompositeExtract 93 1
+ 96: 6(float) CompositeExtract 93 2
+ 97: 10(fvec4) CompositeConstruct 94 95 96 24
+ 98: 10(fvec4) MatrixTimesVector 92 97
+ 100: 99(ptr) AccessChain 89 20
+ Store 100 98
+ 104: 21(ptr) AccessChain 14(params) 103
+ 105: 7(fvec3) Load 104
+ 106: 6(float) Load 75(brightness)
+ 107: 7(fvec3) VectorTimesScalar 105 106
+ Store 102(color) 107
+ Return
+ FunctionEnd
+#endif
+
+static const uint32_t Smoke_push_constant_vert[715] = {
+ 0x07230203, 0x00010000, 0x00080001, 0x0000006c,
+ 0x00000000, 0x00020011, 0x00000001, 0x0006000b,
+ 0x00000001, 0x4c534c47, 0x6474732e, 0x3035342e,
+ 0x00000000, 0x0003000e, 0x00000000, 0x00000001,
+ 0x0009000f, 0x00000000, 0x00000004, 0x6e69616d,
+ 0x00000000, 0x00000026, 0x00000043, 0x00000059,
+ 0x00000066, 0x00030003, 0x00000001, 0x00000136,
+ 0x00040005, 0x00000004, 0x6e69616d, 0x00000000,
+ 0x00050005, 0x00000009, 0x6c726f77, 0x696c5f64,
+ 0x00746867, 0x00050005, 0x0000000c, 0x61726170,
+ 0x6c625f6d, 0x006b636f, 0x00060006, 0x0000000c,
+ 0x00000000, 0x6867696c, 0x6f705f74, 0x00000073,
+ 0x00060006, 0x0000000c, 0x00000001, 0x6867696c,
+ 0x6f635f74, 0x00726f6c, 0x00050006, 0x0000000c,
+ 0x00000002, 0x65646f6d, 0x0000006c, 0x00070006,
+ 0x0000000c, 0x00000003, 0x77656976, 0x6f72705f,
+ 0x7463656a, 0x006e6f69, 0x00040005, 0x0000000e,
+ 0x61726170, 0x0000736d, 0x00050005, 0x00000022,
+ 0x6c726f77, 0x6f705f64, 0x00000073, 0x00040005,
+ 0x00000026, 0x705f6e69, 0x0000736f, 0x00060005,
+ 0x00000031, 0x6c726f77, 0x6f6e5f64, 0x6c616d72,
+ 0x00000000, 0x00050005, 0x00000043, 0x6e5f6e69,
+ 0x616d726f, 0x0000006c, 0x00050005, 0x00000046,
+ 0x6867696c, 0x69645f74, 0x00000072, 0x00050005,
+ 0x0000004b, 0x67697262, 0x656e7468, 0x00007373,
+ 0x00060005, 0x00000057, 0x505f6c67, 0x65567265,
+ 0x78657472, 0x00000000, 0x00060006, 0x00000057,
+ 0x00000000, 0x505f6c67, 0x7469736f, 0x006e6f69,
+ 0x00070006, 0x00000057, 0x00000001, 0x505f6c67,
+ 0x746e696f, 0x657a6953, 0x00000000, 0x00030005,
+ 0x00000059, 0x00000000, 0x00040005, 0x00000066,
+ 0x6f6c6f63, 0x00000072, 0x00050048, 0x0000000c,
+ 0x00000000, 0x00000023, 0x00000000, 0x00050048,
+ 0x0000000c, 0x00000001, 0x00000023, 0x00000010,
+ 0x00040048, 0x0000000c, 0x00000002, 0x00000005,
+ 0x00050048, 0x0000000c, 0x00000002, 0x00000023,
+ 0x00000020, 0x00050048, 0x0000000c, 0x00000002,
+ 0x00000007, 0x00000010, 0x00040048, 0x0000000c,
+ 0x00000003, 0x00000005, 0x00050048, 0x0000000c,
+ 0x00000003, 0x00000023, 0x00000060, 0x00050048,
+ 0x0000000c, 0x00000003, 0x00000007, 0x00000010,
+ 0x00030047, 0x0000000c, 0x00000002, 0x00040047,
+ 0x0000000e, 0x00000022, 0x00000000, 0x00040047,
+ 0x00000026, 0x0000001e, 0x00000000, 0x00040047,
+ 0x00000043, 0x0000001e, 0x00000001, 0x00050048,
+ 0x00000057, 0x00000000, 0x0000000b, 0x00000000,
+ 0x00050048, 0x00000057, 0x00000001, 0x0000000b,
+ 0x00000001, 0x00030047, 0x00000057, 0x00000002,
+ 0x00020013, 0x00000002, 0x00030021, 0x00000003,
+ 0x00000002, 0x00030016, 0x00000006, 0x00000020,
+ 0x00040017, 0x00000007, 0x00000006, 0x00000003,
+ 0x00040020, 0x00000008, 0x00000007, 0x00000007,
+ 0x00040017, 0x0000000a, 0x00000006, 0x00000004,
+ 0x00040018, 0x0000000b, 0x0000000a, 0x00000004,
+ 0x0006001e, 0x0000000c, 0x00000007, 0x00000007,
+ 0x0000000b, 0x0000000b, 0x00040020, 0x0000000d,
+ 0x00000009, 0x0000000c, 0x0004003b, 0x0000000d,
+ 0x0000000e, 0x00000009, 0x00040015, 0x0000000f,
+ 0x00000020, 0x00000001, 0x0004002b, 0x0000000f,
+ 0x00000010, 0x00000002, 0x00040020, 0x00000011,
+ 0x00000009, 0x0000000b, 0x0004002b, 0x0000000f,
+ 0x00000014, 0x00000000, 0x00040020, 0x00000015,
+ 0x00000009, 0x00000007, 0x0004002b, 0x00000006,
+ 0x00000018, 0x3f800000, 0x00040020, 0x00000025,
+ 0x00000001, 0x00000007, 0x0004003b, 0x00000025,
+ 0x00000026, 0x00000001, 0x00040018, 0x00000034,
+ 0x00000007, 0x00000003, 0x0004002b, 0x00000006,
+ 0x00000035, 0x00000000, 0x0004003b, 0x00000025,
+ 0x00000043, 0x00000001, 0x00040020, 0x0000004a,
+ 0x00000007, 0x00000006, 0x0004001e, 0x00000057,
+ 0x0000000a, 0x00000006, 0x00040020, 0x00000058,
+ 0x00000003, 0x00000057, 0x0004003b, 0x00000058,
+ 0x00000059, 0x00000003, 0x0004002b, 0x0000000f,
+ 0x0000005a, 0x00000003, 0x00040020, 0x00000063,
+ 0x00000003, 0x0000000a, 0x00040020, 0x00000065,
+ 0x00000003, 0x00000007, 0x0004003b, 0x00000065,
+ 0x00000066, 0x00000003, 0x0004002b, 0x0000000f,
+ 0x00000067, 0x00000001, 0x00050036, 0x00000002,
+ 0x00000004, 0x00000000, 0x00000003, 0x000200f8,
+ 0x00000005, 0x0004003b, 0x00000008, 0x00000009,
+ 0x00000007, 0x0004003b, 0x00000008, 0x00000022,
+ 0x00000007, 0x0004003b, 0x00000008, 0x00000031,
+ 0x00000007, 0x0004003b, 0x00000008, 0x00000046,
+ 0x00000007, 0x0004003b, 0x0000004a, 0x0000004b,
+ 0x00000007, 0x00050041, 0x00000011, 0x00000012,
+ 0x0000000e, 0x00000010, 0x0004003d, 0x0000000b,
+ 0x00000013, 0x00000012, 0x00050041, 0x00000015,
+ 0x00000016, 0x0000000e, 0x00000014, 0x0004003d,
+ 0x00000007, 0x00000017, 0x00000016, 0x00050051,
+ 0x00000006, 0x00000019, 0x00000017, 0x00000000,
+ 0x00050051, 0x00000006, 0x0000001a, 0x00000017,
+ 0x00000001, 0x00050051, 0x00000006, 0x0000001b,
+ 0x00000017, 0x00000002, 0x00070050, 0x0000000a,
+ 0x0000001c, 0x00000019, 0x0000001a, 0x0000001b,
+ 0x00000018, 0x00050091, 0x0000000a, 0x0000001d,
+ 0x00000013, 0x0000001c, 0x00050051, 0x00000006,
+ 0x0000001e, 0x0000001d, 0x00000000, 0x00050051,
+ 0x00000006, 0x0000001f, 0x0000001d, 0x00000001,
+ 0x00050051, 0x00000006, 0x00000020, 0x0000001d,
+ 0x00000002, 0x00060050, 0x00000007, 0x00000021,
+ 0x0000001e, 0x0000001f, 0x00000020, 0x0003003e,
+ 0x00000009, 0x00000021, 0x00050041, 0x00000011,
+ 0x00000023, 0x0000000e, 0x00000010, 0x0004003d,
+ 0x0000000b, 0x00000024, 0x00000023, 0x0004003d,
+ 0x00000007, 0x00000027, 0x00000026, 0x00050051,
+ 0x00000006, 0x00000028, 0x00000027, 0x00000000,
+ 0x00050051, 0x00000006, 0x00000029, 0x00000027,
+ 0x00000001, 0x00050051, 0x00000006, 0x0000002a,
+ 0x00000027, 0x00000002, 0x00070050, 0x0000000a,
+ 0x0000002b, 0x00000028, 0x00000029, 0x0000002a,
+ 0x00000018, 0x00050091, 0x0000000a, 0x0000002c,
+ 0x00000024, 0x0000002b, 0x00050051, 0x00000006,
+ 0x0000002d, 0x0000002c, 0x00000000, 0x00050051,
+ 0x00000006, 0x0000002e, 0x0000002c, 0x00000001,
+ 0x00050051, 0x00000006, 0x0000002f, 0x0000002c,
+ 0x00000002, 0x00060050, 0x00000007, 0x00000030,
+ 0x0000002d, 0x0000002e, 0x0000002f, 0x0003003e,
+ 0x00000022, 0x00000030, 0x00050041, 0x00000011,
+ 0x00000032, 0x0000000e, 0x00000010, 0x0004003d,
+ 0x0000000b, 0x00000033, 0x00000032, 0x00060051,
+ 0x00000006, 0x00000036, 0x00000033, 0x00000000,
+ 0x00000000, 0x00060051, 0x00000006, 0x00000037,
+ 0x00000033, 0x00000000, 0x00000001, 0x00060051,
+ 0x00000006, 0x00000038, 0x00000033, 0x00000000,
+ 0x00000002, 0x00060051, 0x00000006, 0x00000039,
+ 0x00000033, 0x00000001, 0x00000000, 0x00060051,
+ 0x00000006, 0x0000003a, 0x00000033, 0x00000001,
+ 0x00000001, 0x00060051, 0x00000006, 0x0000003b,
+ 0x00000033, 0x00000001, 0x00000002, 0x00060051,
+ 0x00000006, 0x0000003c, 0x00000033, 0x00000002,
+ 0x00000000, 0x00060051, 0x00000006, 0x0000003d,
+ 0x00000033, 0x00000002, 0x00000001, 0x00060051,
+ 0x00000006, 0x0000003e, 0x00000033, 0x00000002,
+ 0x00000002, 0x00060050, 0x00000007, 0x0000003f,
+ 0x00000036, 0x00000037, 0x00000038, 0x00060050,
+ 0x00000007, 0x00000040, 0x00000039, 0x0000003a,
+ 0x0000003b, 0x00060050, 0x00000007, 0x00000041,
+ 0x0000003c, 0x0000003d, 0x0000003e, 0x00060050,
+ 0x00000034, 0x00000042, 0x0000003f, 0x00000040,
+ 0x00000041, 0x0004003d, 0x00000007, 0x00000044,
+ 0x00000043, 0x00050091, 0x00000007, 0x00000045,
+ 0x00000042, 0x00000044, 0x0003003e, 0x00000031,
+ 0x00000045, 0x0004003d, 0x00000007, 0x00000047,
+ 0x00000009, 0x0004003d, 0x00000007, 0x00000048,
+ 0x00000022, 0x00050083, 0x00000007, 0x00000049,
+ 0x00000047, 0x00000048, 0x0003003e, 0x00000046,
+ 0x00000049, 0x0004003d, 0x00000007, 0x0000004c,
+ 0x00000046, 0x0004003d, 0x00000007, 0x0000004d,
+ 0x00000031, 0x00050094, 0x00000006, 0x0000004e,
+ 0x0000004c, 0x0000004d, 0x0004003d, 0x00000007,
+ 0x0000004f, 0x00000046, 0x0006000c, 0x00000006,
+ 0x00000050, 0x00000001, 0x00000042, 0x0000004f,
+ 0x00050088, 0x00000006, 0x00000051, 0x0000004e,
+ 0x00000050, 0x0004003d, 0x00000007, 0x00000052,
+ 0x00000031, 0x0006000c, 0x00000006, 0x00000053,
+ 0x00000001, 0x00000042, 0x00000052, 0x00050088,
+ 0x00000006, 0x00000054, 0x00000051, 0x00000053,
+ 0x0003003e, 0x0000004b, 0x00000054, 0x0004003d,
+ 0x00000006, 0x00000055, 0x0000004b, 0x0006000c,
+ 0x00000006, 0x00000056, 0x00000001, 0x00000004,
+ 0x00000055, 0x0003003e, 0x0000004b, 0x00000056,
+ 0x00050041, 0x00000011, 0x0000005b, 0x0000000e,
+ 0x0000005a, 0x0004003d, 0x0000000b, 0x0000005c,
+ 0x0000005b, 0x0004003d, 0x00000007, 0x0000005d,
+ 0x00000022, 0x00050051, 0x00000006, 0x0000005e,
+ 0x0000005d, 0x00000000, 0x00050051, 0x00000006,
+ 0x0000005f, 0x0000005d, 0x00000001, 0x00050051,
+ 0x00000006, 0x00000060, 0x0000005d, 0x00000002,
+ 0x00070050, 0x0000000a, 0x00000061, 0x0000005e,
+ 0x0000005f, 0x00000060, 0x00000018, 0x00050091,
+ 0x0000000a, 0x00000062, 0x0000005c, 0x00000061,
+ 0x00050041, 0x00000063, 0x00000064, 0x00000059,
+ 0x00000014, 0x0003003e, 0x00000064, 0x00000062,
+ 0x00050041, 0x00000015, 0x00000068, 0x0000000e,
+ 0x00000067, 0x0004003d, 0x00000007, 0x00000069,
+ 0x00000068, 0x0004003d, 0x00000006, 0x0000006a,
+ 0x0000004b, 0x0005008e, 0x00000007, 0x0000006b,
+ 0x00000069, 0x0000006a, 0x0003003e, 0x00000066,
+ 0x0000006b, 0x000100fd, 0x00010038,
+};
diff --git a/demos/smoke/android/src/main/jni/Smoke.vert.h b/demos/smoke/android/src/main/jni/Smoke.vert.h
new file mode 100644
index 00000000..ac59ed48
--- /dev/null
+++ b/demos/smoke/android/src/main/jni/Smoke.vert.h
@@ -0,0 +1,354 @@
+#include <stdint.h>
+
+#if 0
+/usr/local/google/home/olv/khronos/VulkanSamples/Demos/Hologram/Hologram.vert
+Warning, version 310 is not yet complete; most version-specific features are present, but some are missing.
+
+
+Linked vertex stage:
+
+
+// Module Version 10000
+// Generated by (magic number): 80001
+// Id's are bound by 108
+
+ Capability Shader
+ 1: ExtInstImport "GLSL.std.450"
+ MemoryModel Logical GLSL450
+ EntryPoint Vertex 4 "main" 38 67 89 102
+ Source ESSL 310
+ Name 4 "main"
+ Name 9 "world_light"
+ Name 12 "param_block"
+ MemberName 12(param_block) 0 "light_pos"
+ MemberName 12(param_block) 1 "light_color"
+ MemberName 12(param_block) 2 "model"
+ MemberName 12(param_block) 3 "view_projection"
+ Name 14 "params"
+ Name 34 "world_pos"
+ Name 38 "in_pos"
+ Name 49 "world_normal"
+ Name 67 "in_normal"
+ Name 70 "light_dir"
+ Name 75 "brightness"
+ Name 87 "gl_PerVertex"
+ MemberName 87(gl_PerVertex) 0 "gl_Position"
+ MemberName 87(gl_PerVertex) 1 "gl_PointSize"
+ Name 89 ""
+ Name 102 "color"
+ MemberDecorate 12(param_block) 0 Offset 0
+ MemberDecorate 12(param_block) 1 Offset 16
+ MemberDecorate 12(param_block) 2 ColMajor
+ MemberDecorate 12(param_block) 2 Offset 32
+ MemberDecorate 12(param_block) 2 MatrixStride 16
+ MemberDecorate 12(param_block) 3 ColMajor
+ MemberDecorate 12(param_block) 3 Offset 96
+ MemberDecorate 12(param_block) 3 MatrixStride 16
+ Decorate 12(param_block) BufferBlock
+ Decorate 14(params) DescriptorSet 0
+ Decorate 14(params) Binding 0
+ Decorate 38(in_pos) Location 0
+ Decorate 67(in_normal) Location 1
+ MemberDecorate 87(gl_PerVertex) 0 BuiltIn Position
+ MemberDecorate 87(gl_PerVertex) 1 BuiltIn PointSize
+ Decorate 87(gl_PerVertex) Block
+ 2: TypeVoid
+ 3: TypeFunction 2
+ 6: TypeFloat 32
+ 7: TypeVector 6(float) 3
+ 8: TypePointer Function 7(fvec3)
+ 10: TypeVector 6(float) 4
+ 11: TypeMatrix 10(fvec4) 4
+ 12(param_block): TypeStruct 7(fvec3) 7(fvec3) 11 11
+ 13: TypePointer Uniform 12(param_block)
+ 14(params): 13(ptr) Variable Uniform
+ 15: TypeInt 32 1
+ 16: 15(int) Constant 2
+ 17: TypePointer Uniform 11
+ 20: 15(int) Constant 0
+ 21: TypePointer Uniform 7(fvec3)
+ 24: 6(float) Constant 1065353216
+ 37: TypePointer Input 7(fvec3)
+ 38(in_pos): 37(ptr) Variable Input
+ 52: TypeMatrix 7(fvec3) 3
+ 53: 6(float) Constant 0
+ 67(in_normal): 37(ptr) Variable Input
+ 74: TypePointer Function 6(float)
+87(gl_PerVertex): TypeStruct 10(fvec4) 6(float)
+ 88: TypePointer Output 87(gl_PerVertex)
+ 89: 88(ptr) Variable Output
+ 90: 15(int) Constant 3
+ 99: TypePointer Output 10(fvec4)
+ 101: TypePointer Output 7(fvec3)
+ 102(color): 101(ptr) Variable Output
+ 103: 15(int) Constant 1
+ 4(main): 2 Function None 3
+ 5: Label
+ 9(world_light): 8(ptr) Variable Function
+ 34(world_pos): 8(ptr) Variable Function
+49(world_normal): 8(ptr) Variable Function
+ 70(light_dir): 8(ptr) Variable Function
+ 75(brightness): 74(ptr) Variable Function
+ 18: 17(ptr) AccessChain 14(params) 16
+ 19: 11 Load 18
+ 22: 21(ptr) AccessChain 14(params) 20
+ 23: 7(fvec3) Load 22
+ 25: 6(float) CompositeExtract 23 0
+ 26: 6(float) CompositeExtract 23 1
+ 27: 6(float) CompositeExtract 23 2
+ 28: 10(fvec4) CompositeConstruct 25 26 27 24
+ 29: 10(fvec4) MatrixTimesVector 19 28
+ 30: 6(float) CompositeExtract 29 0
+ 31: 6(float) CompositeExtract 29 1
+ 32: 6(float) CompositeExtract 29 2
+ 33: 7(fvec3) CompositeConstruct 30 31 32
+ Store 9(world_light) 33
+ 35: 17(ptr) AccessChain 14(params) 16
+ 36: 11 Load 35
+ 39: 7(fvec3) Load 38(in_pos)
+ 40: 6(float) CompositeExtract 39 0
+ 41: 6(float) CompositeExtract 39 1
+ 42: 6(float) CompositeExtract 39 2
+ 43: 10(fvec4) CompositeConstruct 40 41 42 24
+ 44: 10(fvec4) MatrixTimesVector 36 43
+ 45: 6(float) CompositeExtract 44 0
+ 46: 6(float) CompositeExtract 44 1
+ 47: 6(float) CompositeExtract 44 2
+ 48: 7(fvec3) CompositeConstruct 45 46 47
+ Store 34(world_pos) 48
+ 50: 17(ptr) AccessChain 14(params) 16
+ 51: 11 Load 50
+ 54: 6(float) CompositeExtract 51 0 0
+ 55: 6(float) CompositeExtract 51 0 1
+ 56: 6(float) CompositeExtract 51 0 2
+ 57: 6(float) CompositeExtract 51 1 0
+ 58: 6(float) CompositeExtract 51 1 1
+ 59: 6(float) CompositeExtract 51 1 2
+ 60: 6(float) CompositeExtract 51 2 0
+ 61: 6(float) CompositeExtract 51 2 1
+ 62: 6(float) CompositeExtract 51 2 2
+ 63: 7(fvec3) CompositeConstruct 54 55 56
+ 64: 7(fvec3) CompositeConstruct 57 58 59
+ 65: 7(fvec3) CompositeConstruct 60 61 62
+ 66: 52 CompositeConstruct 63 64 65
+ 68: 7(fvec3) Load 67(in_normal)
+ 69: 7(fvec3) MatrixTimesVector 66 68
+ Store 49(world_normal) 69
+ 71: 7(fvec3) Load 9(world_light)
+ 72: 7(fvec3) Load 34(world_pos)
+ 73: 7(fvec3) FSub 71 72
+ Store 70(light_dir) 73
+ 76: 7(fvec3) Load 70(light_dir)
+ 77: 7(fvec3) Load 49(world_normal)
+ 78: 6(float) Dot 76 77
+ 79: 7(fvec3) Load 70(light_dir)
+ 80: 6(float) ExtInst 1(GLSL.std.450) 66(Length) 79
+ 81: 6(float) FDiv 78 80
+ 82: 7(fvec3) Load 49(world_normal)
+ 83: 6(float) ExtInst 1(GLSL.std.450) 66(Length) 82
+ 84: 6(float) FDiv 81 83
+ Store 75(brightness) 84
+ 85: 6(float) Load 75(brightness)
+ 86: 6(float) ExtInst 1(GLSL.std.450) 4(FAbs) 85
+ Store 75(brightness) 86
+ 91: 17(ptr) AccessChain 14(params) 90
+ 92: 11 Load 91
+ 93: 7(fvec3) Load 34(world_pos)
+ 94: 6(float) CompositeExtract 93 0
+ 95: 6(float) CompositeExtract 93 1
+ 96: 6(float) CompositeExtract 93 2
+ 97: 10(fvec4) CompositeConstruct 94 95 96 24
+ 98: 10(fvec4) MatrixTimesVector 92 97
+ 100: 99(ptr) AccessChain 89 20
+ Store 100 98
+ 104: 21(ptr) AccessChain 14(params) 103
+ 105: 7(fvec3) Load 104
+ 106: 6(float) Load 75(brightness)
+ 107: 7(fvec3) VectorTimesScalar 105 106
+ Store 102(color) 107
+ Return
+ FunctionEnd
+#endif
+
+static const uint32_t Smoke_vert[719] = {
+ 0x07230203, 0x00010000, 0x00080001, 0x0000006c,
+ 0x00000000, 0x00020011, 0x00000001, 0x0006000b,
+ 0x00000001, 0x4c534c47, 0x6474732e, 0x3035342e,
+ 0x00000000, 0x0003000e, 0x00000000, 0x00000001,
+ 0x0009000f, 0x00000000, 0x00000004, 0x6e69616d,
+ 0x00000000, 0x00000026, 0x00000043, 0x00000059,
+ 0x00000066, 0x00030003, 0x00000001, 0x00000136,
+ 0x00040005, 0x00000004, 0x6e69616d, 0x00000000,
+ 0x00050005, 0x00000009, 0x6c726f77, 0x696c5f64,
+ 0x00746867, 0x00050005, 0x0000000c, 0x61726170,
+ 0x6c625f6d, 0x006b636f, 0x00060006, 0x0000000c,
+ 0x00000000, 0x6867696c, 0x6f705f74, 0x00000073,
+ 0x00060006, 0x0000000c, 0x00000001, 0x6867696c,
+ 0x6f635f74, 0x00726f6c, 0x00050006, 0x0000000c,
+ 0x00000002, 0x65646f6d, 0x0000006c, 0x00070006,
+ 0x0000000c, 0x00000003, 0x77656976, 0x6f72705f,
+ 0x7463656a, 0x006e6f69, 0x00040005, 0x0000000e,
+ 0x61726170, 0x0000736d, 0x00050005, 0x00000022,
+ 0x6c726f77, 0x6f705f64, 0x00000073, 0x00040005,
+ 0x00000026, 0x705f6e69, 0x0000736f, 0x00060005,
+ 0x00000031, 0x6c726f77, 0x6f6e5f64, 0x6c616d72,
+ 0x00000000, 0x00050005, 0x00000043, 0x6e5f6e69,
+ 0x616d726f, 0x0000006c, 0x00050005, 0x00000046,
+ 0x6867696c, 0x69645f74, 0x00000072, 0x00050005,
+ 0x0000004b, 0x67697262, 0x656e7468, 0x00007373,
+ 0x00060005, 0x00000057, 0x505f6c67, 0x65567265,
+ 0x78657472, 0x00000000, 0x00060006, 0x00000057,
+ 0x00000000, 0x505f6c67, 0x7469736f, 0x006e6f69,
+ 0x00070006, 0x00000057, 0x00000001, 0x505f6c67,
+ 0x746e696f, 0x657a6953, 0x00000000, 0x00030005,
+ 0x00000059, 0x00000000, 0x00040005, 0x00000066,
+ 0x6f6c6f63, 0x00000072, 0x00050048, 0x0000000c,
+ 0x00000000, 0x00000023, 0x00000000, 0x00050048,
+ 0x0000000c, 0x00000001, 0x00000023, 0x00000010,
+ 0x00040048, 0x0000000c, 0x00000002, 0x00000005,
+ 0x00050048, 0x0000000c, 0x00000002, 0x00000023,
+ 0x00000020, 0x00050048, 0x0000000c, 0x00000002,
+ 0x00000007, 0x00000010, 0x00040048, 0x0000000c,
+ 0x00000003, 0x00000005, 0x00050048, 0x0000000c,
+ 0x00000003, 0x00000023, 0x00000060, 0x00050048,
+ 0x0000000c, 0x00000003, 0x00000007, 0x00000010,
+ 0x00030047, 0x0000000c, 0x00000003, 0x00040047,
+ 0x0000000e, 0x00000022, 0x00000000, 0x00040047,
+ 0x0000000e, 0x00000021, 0x00000000, 0x00040047,
+ 0x00000026, 0x0000001e, 0x00000000, 0x00040047,
+ 0x00000043, 0x0000001e, 0x00000001, 0x00050048,
+ 0x00000057, 0x00000000, 0x0000000b, 0x00000000,
+ 0x00050048, 0x00000057, 0x00000001, 0x0000000b,
+ 0x00000001, 0x00030047, 0x00000057, 0x00000002,
+ 0x00020013, 0x00000002, 0x00030021, 0x00000003,
+ 0x00000002, 0x00030016, 0x00000006, 0x00000020,
+ 0x00040017, 0x00000007, 0x00000006, 0x00000003,
+ 0x00040020, 0x00000008, 0x00000007, 0x00000007,
+ 0x00040017, 0x0000000a, 0x00000006, 0x00000004,
+ 0x00040018, 0x0000000b, 0x0000000a, 0x00000004,
+ 0x0006001e, 0x0000000c, 0x00000007, 0x00000007,
+ 0x0000000b, 0x0000000b, 0x00040020, 0x0000000d,
+ 0x00000002, 0x0000000c, 0x0004003b, 0x0000000d,
+ 0x0000000e, 0x00000002, 0x00040015, 0x0000000f,
+ 0x00000020, 0x00000001, 0x0004002b, 0x0000000f,
+ 0x00000010, 0x00000002, 0x00040020, 0x00000011,
+ 0x00000002, 0x0000000b, 0x0004002b, 0x0000000f,
+ 0x00000014, 0x00000000, 0x00040020, 0x00000015,
+ 0x00000002, 0x00000007, 0x0004002b, 0x00000006,
+ 0x00000018, 0x3f800000, 0x00040020, 0x00000025,
+ 0x00000001, 0x00000007, 0x0004003b, 0x00000025,
+ 0x00000026, 0x00000001, 0x00040018, 0x00000034,
+ 0x00000007, 0x00000003, 0x0004002b, 0x00000006,
+ 0x00000035, 0x00000000, 0x0004003b, 0x00000025,
+ 0x00000043, 0x00000001, 0x00040020, 0x0000004a,
+ 0x00000007, 0x00000006, 0x0004001e, 0x00000057,
+ 0x0000000a, 0x00000006, 0x00040020, 0x00000058,
+ 0x00000003, 0x00000057, 0x0004003b, 0x00000058,
+ 0x00000059, 0x00000003, 0x0004002b, 0x0000000f,
+ 0x0000005a, 0x00000003, 0x00040020, 0x00000063,
+ 0x00000003, 0x0000000a, 0x00040020, 0x00000065,
+ 0x00000003, 0x00000007, 0x0004003b, 0x00000065,
+ 0x00000066, 0x00000003, 0x0004002b, 0x0000000f,
+ 0x00000067, 0x00000001, 0x00050036, 0x00000002,
+ 0x00000004, 0x00000000, 0x00000003, 0x000200f8,
+ 0x00000005, 0x0004003b, 0x00000008, 0x00000009,
+ 0x00000007, 0x0004003b, 0x00000008, 0x00000022,
+ 0x00000007, 0x0004003b, 0x00000008, 0x00000031,
+ 0x00000007, 0x0004003b, 0x00000008, 0x00000046,
+ 0x00000007, 0x0004003b, 0x0000004a, 0x0000004b,
+ 0x00000007, 0x00050041, 0x00000011, 0x00000012,
+ 0x0000000e, 0x00000010, 0x0004003d, 0x0000000b,
+ 0x00000013, 0x00000012, 0x00050041, 0x00000015,
+ 0x00000016, 0x0000000e, 0x00000014, 0x0004003d,
+ 0x00000007, 0x00000017, 0x00000016, 0x00050051,
+ 0x00000006, 0x00000019, 0x00000017, 0x00000000,
+ 0x00050051, 0x00000006, 0x0000001a, 0x00000017,
+ 0x00000001, 0x00050051, 0x00000006, 0x0000001b,
+ 0x00000017, 0x00000002, 0x00070050, 0x0000000a,
+ 0x0000001c, 0x00000019, 0x0000001a, 0x0000001b,
+ 0x00000018, 0x00050091, 0x0000000a, 0x0000001d,
+ 0x00000013, 0x0000001c, 0x00050051, 0x00000006,
+ 0x0000001e, 0x0000001d, 0x00000000, 0x00050051,
+ 0x00000006, 0x0000001f, 0x0000001d, 0x00000001,
+ 0x00050051, 0x00000006, 0x00000020, 0x0000001d,
+ 0x00000002, 0x00060050, 0x00000007, 0x00000021,
+ 0x0000001e, 0x0000001f, 0x00000020, 0x0003003e,
+ 0x00000009, 0x00000021, 0x00050041, 0x00000011,
+ 0x00000023, 0x0000000e, 0x00000010, 0x0004003d,
+ 0x0000000b, 0x00000024, 0x00000023, 0x0004003d,
+ 0x00000007, 0x00000027, 0x00000026, 0x00050051,
+ 0x00000006, 0x00000028, 0x00000027, 0x00000000,
+ 0x00050051, 0x00000006, 0x00000029, 0x00000027,
+ 0x00000001, 0x00050051, 0x00000006, 0x0000002a,
+ 0x00000027, 0x00000002, 0x00070050, 0x0000000a,
+ 0x0000002b, 0x00000028, 0x00000029, 0x0000002a,
+ 0x00000018, 0x00050091, 0x0000000a, 0x0000002c,
+ 0x00000024, 0x0000002b, 0x00050051, 0x00000006,
+ 0x0000002d, 0x0000002c, 0x00000000, 0x00050051,
+ 0x00000006, 0x0000002e, 0x0000002c, 0x00000001,
+ 0x00050051, 0x00000006, 0x0000002f, 0x0000002c,
+ 0x00000002, 0x00060050, 0x00000007, 0x00000030,
+ 0x0000002d, 0x0000002e, 0x0000002f, 0x0003003e,
+ 0x00000022, 0x00000030, 0x00050041, 0x00000011,
+ 0x00000032, 0x0000000e, 0x00000010, 0x0004003d,
+ 0x0000000b, 0x00000033, 0x00000032, 0x00060051,
+ 0x00000006, 0x00000036, 0x00000033, 0x00000000,
+ 0x00000000, 0x00060051, 0x00000006, 0x00000037,
+ 0x00000033, 0x00000000, 0x00000001, 0x00060051,
+ 0x00000006, 0x00000038, 0x00000033, 0x00000000,
+ 0x00000002, 0x00060051, 0x00000006, 0x00000039,
+ 0x00000033, 0x00000001, 0x00000000, 0x00060051,
+ 0x00000006, 0x0000003a, 0x00000033, 0x00000001,
+ 0x00000001, 0x00060051, 0x00000006, 0x0000003b,
+ 0x00000033, 0x00000001, 0x00000002, 0x00060051,
+ 0x00000006, 0x0000003c, 0x00000033, 0x00000002,
+ 0x00000000, 0x00060051, 0x00000006, 0x0000003d,
+ 0x00000033, 0x00000002, 0x00000001, 0x00060051,
+ 0x00000006, 0x0000003e, 0x00000033, 0x00000002,
+ 0x00000002, 0x00060050, 0x00000007, 0x0000003f,
+ 0x00000036, 0x00000037, 0x00000038, 0x00060050,
+ 0x00000007, 0x00000040, 0x00000039, 0x0000003a,
+ 0x0000003b, 0x00060050, 0x00000007, 0x00000041,
+ 0x0000003c, 0x0000003d, 0x0000003e, 0x00060050,
+ 0x00000034, 0x00000042, 0x0000003f, 0x00000040,
+ 0x00000041, 0x0004003d, 0x00000007, 0x00000044,
+ 0x00000043, 0x00050091, 0x00000007, 0x00000045,
+ 0x00000042, 0x00000044, 0x0003003e, 0x00000031,
+ 0x00000045, 0x0004003d, 0x00000007, 0x00000047,
+ 0x00000009, 0x0004003d, 0x00000007, 0x00000048,
+ 0x00000022, 0x00050083, 0x00000007, 0x00000049,
+ 0x00000047, 0x00000048, 0x0003003e, 0x00000046,
+ 0x00000049, 0x0004003d, 0x00000007, 0x0000004c,
+ 0x00000046, 0x0004003d, 0x00000007, 0x0000004d,
+ 0x00000031, 0x00050094, 0x00000006, 0x0000004e,
+ 0x0000004c, 0x0000004d, 0x0004003d, 0x00000007,
+ 0x0000004f, 0x00000046, 0x0006000c, 0x00000006,
+ 0x00000050, 0x00000001, 0x00000042, 0x0000004f,
+ 0x00050088, 0x00000006, 0x00000051, 0x0000004e,
+ 0x00000050, 0x0004003d, 0x00000007, 0x00000052,
+ 0x00000031, 0x0006000c, 0x00000006, 0x00000053,
+ 0x00000001, 0x00000042, 0x00000052, 0x00050088,
+ 0x00000006, 0x00000054, 0x00000051, 0x00000053,
+ 0x0003003e, 0x0000004b, 0x00000054, 0x0004003d,
+ 0x00000006, 0x00000055, 0x0000004b, 0x0006000c,
+ 0x00000006, 0x00000056, 0x00000001, 0x00000004,
+ 0x00000055, 0x0003003e, 0x0000004b, 0x00000056,
+ 0x00050041, 0x00000011, 0x0000005b, 0x0000000e,
+ 0x0000005a, 0x0004003d, 0x0000000b, 0x0000005c,
+ 0x0000005b, 0x0004003d, 0x00000007, 0x0000005d,
+ 0x00000022, 0x00050051, 0x00000006, 0x0000005e,
+ 0x0000005d, 0x00000000, 0x00050051, 0x00000006,
+ 0x0000005f, 0x0000005d, 0x00000001, 0x00050051,
+ 0x00000006, 0x00000060, 0x0000005d, 0x00000002,
+ 0x00070050, 0x0000000a, 0x00000061, 0x0000005e,
+ 0x0000005f, 0x00000060, 0x00000018, 0x00050091,
+ 0x0000000a, 0x00000062, 0x0000005c, 0x00000061,
+ 0x00050041, 0x00000063, 0x00000064, 0x00000059,
+ 0x00000014, 0x0003003e, 0x00000064, 0x00000062,
+ 0x00050041, 0x00000015, 0x00000068, 0x0000000e,
+ 0x00000067, 0x0004003d, 0x00000007, 0x00000069,
+ 0x00000068, 0x0004003d, 0x00000006, 0x0000006a,
+ 0x0000004b, 0x0005008e, 0x00000007, 0x0000006b,
+ 0x00000069, 0x0000006a, 0x0003003e, 0x00000066,
+ 0x0000006b, 0x000100fd, 0x00010038,
+};
diff --git a/demos/smoke/android/src/main/res/values/strings.xml b/demos/smoke/android/src/main/res/values/strings.xml
new file mode 100644
index 00000000..c82554f1
--- /dev/null
+++ b/demos/smoke/android/src/main/res/values/strings.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_name">Smoke</string>
+</resources>
diff --git a/demos/smoke/generate-dispatch-table b/demos/smoke/generate-dispatch-table
new file mode 100755
index 00000000..803cf52d
--- /dev/null
+++ b/demos/smoke/generate-dispatch-table
@@ -0,0 +1,498 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2016 Google, Inc.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+
+"""Generate Vulkan dispatch table.
+"""
+
+import os
+import sys
+
+class Command(object):
+ PLATFORM = 0
+ LOADER = 1
+ INSTANCE = 2
+ DEVICE = 3
+
+ def __init__(self, name, dispatch):
+ self.name = name
+ self.dispatch = dispatch
+ self.ty = self._get_type()
+
+ @staticmethod
+ def valid_c_typedef(c):
+ return (c.startswith("typedef") and
+ c.endswith(");") and
+ "*PFN_vkVoidFunction" not in c)
+
+ @classmethod
+ def from_c_typedef(cls, c):
+ name_begin = c.find("*PFN_vk") + 7
+ name_end = c.find(")(", name_begin)
+ name = c[name_begin:name_end]
+
+ dispatch_begin = name_end + 2
+ dispatch_end = c.find(" ", dispatch_begin)
+ dispatch = c[dispatch_begin:dispatch_end]
+ if not dispatch.startswith("Vk"):
+ dispatch = None
+
+ return cls(name, dispatch)
+
+ def _get_type(self):
+ if self.dispatch:
+ if self.dispatch in ["VkDevice", "VkQueue", "VkCommandBuffer"]:
+ return self.DEVICE
+ else:
+ return self.INSTANCE
+ else:
+ if self.name in ["GetInstanceProcAddr"]:
+ return self.PLATFORM
+ else:
+ return self.LOADER
+
+ def __repr__(self):
+ return "Command(name=%s, dispatch=%s)" % \
+ (repr(self.name), repr(self.dispatch))
+
+class Extension(object):
+ def __init__(self, name, version, guard=None, commands=[]):
+ self.name = name
+ self.version = version
+ self.guard = guard
+ self.commands = commands[:]
+
+ def add_command(self, cmd):
+ self.commands.append(cmd)
+
+ def __repr__(self):
+ lines = []
+ lines.append("Extension(name=%s, version=%s, guard=%s, commands=[" %
+ (repr(self.name), repr(self.version), repr(self.guard)))
+
+ for cmd in self.commands:
+ lines.append(" %s," % repr(cmd))
+
+ lines.append("])")
+
+ return "\n".join(lines)
+
+# generated by "generate-dispatch-table parse vulkan.h"
+vk_core = Extension(name='VK_core', version=0, guard=None, commands=[
+ Command(name='CreateInstance', dispatch=None),
+ Command(name='DestroyInstance', dispatch='VkInstance'),
+ Command(name='EnumeratePhysicalDevices', dispatch='VkInstance'),
+ Command(name='GetPhysicalDeviceFeatures', dispatch='VkPhysicalDevice'),
+ Command(name='GetPhysicalDeviceFormatProperties', dispatch='VkPhysicalDevice'),
+ Command(name='GetPhysicalDeviceImageFormatProperties', dispatch='VkPhysicalDevice'),
+ Command(name='GetPhysicalDeviceProperties', dispatch='VkPhysicalDevice'),
+ Command(name='GetPhysicalDeviceQueueFamilyProperties', dispatch='VkPhysicalDevice'),
+ Command(name='GetPhysicalDeviceMemoryProperties', dispatch='VkPhysicalDevice'),
+ Command(name='GetInstanceProcAddr', dispatch='VkInstance'),
+ Command(name='GetDeviceProcAddr', dispatch='VkDevice'),
+ Command(name='CreateDevice', dispatch='VkPhysicalDevice'),
+ Command(name='DestroyDevice', dispatch='VkDevice'),
+ Command(name='EnumerateInstanceExtensionProperties', dispatch=None),
+ Command(name='EnumerateDeviceExtensionProperties', dispatch='VkPhysicalDevice'),
+ Command(name='EnumerateInstanceLayerProperties', dispatch=None),
+ Command(name='EnumerateDeviceLayerProperties', dispatch='VkPhysicalDevice'),
+ Command(name='GetDeviceQueue', dispatch='VkDevice'),
+ Command(name='QueueSubmit', dispatch='VkQueue'),
+ Command(name='QueueWaitIdle', dispatch='VkQueue'),
+ Command(name='DeviceWaitIdle', dispatch='VkDevice'),
+ Command(name='AllocateMemory', dispatch='VkDevice'),
+ Command(name='FreeMemory', dispatch='VkDevice'),
+ Command(name='MapMemory', dispatch='VkDevice'),
+ Command(name='UnmapMemory', dispatch='VkDevice'),
+ Command(name='FlushMappedMemoryRanges', dispatch='VkDevice'),
+ Command(name='InvalidateMappedMemoryRanges', dispatch='VkDevice'),
+ Command(name='GetDeviceMemoryCommitment', dispatch='VkDevice'),
+ Command(name='BindBufferMemory', dispatch='VkDevice'),
+ Command(name='BindImageMemory', dispatch='VkDevice'),
+ Command(name='GetBufferMemoryRequirements', dispatch='VkDevice'),
+ Command(name='GetImageMemoryRequirements', dispatch='VkDevice'),
+ Command(name='GetImageSparseMemoryRequirements', dispatch='VkDevice'),
+ Command(name='GetPhysicalDeviceSparseImageFormatProperties', dispatch='VkPhysicalDevice'),
+ Command(name='QueueBindSparse', dispatch='VkQueue'),
+ Command(name='CreateFence', dispatch='VkDevice'),
+ Command(name='DestroyFence', dispatch='VkDevice'),
+ Command(name='ResetFences', dispatch='VkDevice'),
+ Command(name='GetFenceStatus', dispatch='VkDevice'),
+ Command(name='WaitForFences', dispatch='VkDevice'),
+ Command(name='CreateSemaphore', dispatch='VkDevice'),
+ Command(name='DestroySemaphore', dispatch='VkDevice'),
+ Command(name='CreateEvent', dispatch='VkDevice'),
+ Command(name='DestroyEvent', dispatch='VkDevice'),
+ Command(name='GetEventStatus', dispatch='VkDevice'),
+ Command(name='SetEvent', dispatch='VkDevice'),
+ Command(name='ResetEvent', dispatch='VkDevice'),
+ Command(name='CreateQueryPool', dispatch='VkDevice'),
+ Command(name='DestroyQueryPool', dispatch='VkDevice'),
+ Command(name='GetQueryPoolResults', dispatch='VkDevice'),
+ Command(name='CreateBuffer', dispatch='VkDevice'),
+ Command(name='DestroyBuffer', dispatch='VkDevice'),
+ Command(name='CreateBufferView', dispatch='VkDevice'),
+ Command(name='DestroyBufferView', dispatch='VkDevice'),
+ Command(name='CreateImage', dispatch='VkDevice'),
+ Command(name='DestroyImage', dispatch='VkDevice'),
+ Command(name='GetImageSubresourceLayout', dispatch='VkDevice'),
+ Command(name='CreateImageView', dispatch='VkDevice'),
+ Command(name='DestroyImageView', dispatch='VkDevice'),
+ Command(name='CreateShaderModule', dispatch='VkDevice'),
+ Command(name='DestroyShaderModule', dispatch='VkDevice'),
+ Command(name='CreatePipelineCache', dispatch='VkDevice'),
+ Command(name='DestroyPipelineCache', dispatch='VkDevice'),
+ Command(name='GetPipelineCacheData', dispatch='VkDevice'),
+ Command(name='MergePipelineCaches', dispatch='VkDevice'),
+ Command(name='CreateGraphicsPipelines', dispatch='VkDevice'),
+ Command(name='CreateComputePipelines', dispatch='VkDevice'),
+ Command(name='DestroyPipeline', dispatch='VkDevice'),
+ Command(name='CreatePipelineLayout', dispatch='VkDevice'),
+ Command(name='DestroyPipelineLayout', dispatch='VkDevice'),
+ Command(name='CreateSampler', dispatch='VkDevice'),
+ Command(name='DestroySampler', dispatch='VkDevice'),
+ Command(name='CreateDescriptorSetLayout', dispatch='VkDevice'),
+ Command(name='DestroyDescriptorSetLayout', dispatch='VkDevice'),
+ Command(name='CreateDescriptorPool', dispatch='VkDevice'),
+ Command(name='DestroyDescriptorPool', dispatch='VkDevice'),
+ Command(name='ResetDescriptorPool', dispatch='VkDevice'),
+ Command(name='AllocateDescriptorSets', dispatch='VkDevice'),
+ Command(name='FreeDescriptorSets', dispatch='VkDevice'),
+ Command(name='UpdateDescriptorSets', dispatch='VkDevice'),
+ Command(name='CreateFramebuffer', dispatch='VkDevice'),
+ Command(name='DestroyFramebuffer', dispatch='VkDevice'),
+ Command(name='CreateRenderPass', dispatch='VkDevice'),
+ Command(name='DestroyRenderPass', dispatch='VkDevice'),
+ Command(name='GetRenderAreaGranularity', dispatch='VkDevice'),
+ Command(name='CreateCommandPool', dispatch='VkDevice'),
+ Command(name='DestroyCommandPool', dispatch='VkDevice'),
+ Command(name='ResetCommandPool', dispatch='VkDevice'),
+ Command(name='AllocateCommandBuffers', dispatch='VkDevice'),
+ Command(name='FreeCommandBuffers', dispatch='VkDevice'),
+ Command(name='BeginCommandBuffer', dispatch='VkCommandBuffer'),
+ Command(name='EndCommandBuffer', dispatch='VkCommandBuffer'),
+ Command(name='ResetCommandBuffer', dispatch='VkCommandBuffer'),
+ Command(name='CmdBindPipeline', dispatch='VkCommandBuffer'),
+ Command(name='CmdSetViewport', dispatch='VkCommandBuffer'),
+ Command(name='CmdSetScissor', dispatch='VkCommandBuffer'),
+ Command(name='CmdSetLineWidth', dispatch='VkCommandBuffer'),
+ Command(name='CmdSetDepthBias', dispatch='VkCommandBuffer'),
+ Command(name='CmdSetBlendConstants', dispatch='VkCommandBuffer'),
+ Command(name='CmdSetDepthBounds', dispatch='VkCommandBuffer'),
+ Command(name='CmdSetStencilCompareMask', dispatch='VkCommandBuffer'),
+ Command(name='CmdSetStencilWriteMask', dispatch='VkCommandBuffer'),
+ Command(name='CmdSetStencilReference', dispatch='VkCommandBuffer'),
+ Command(name='CmdBindDescriptorSets', dispatch='VkCommandBuffer'),
+ Command(name='CmdBindIndexBuffer', dispatch='VkCommandBuffer'),
+ Command(name='CmdBindVertexBuffers', dispatch='VkCommandBuffer'),
+ Command(name='CmdDraw', dispatch='VkCommandBuffer'),
+ Command(name='CmdDrawIndexed', dispatch='VkCommandBuffer'),
+ Command(name='CmdDrawIndirect', dispatch='VkCommandBuffer'),
+ Command(name='CmdDrawIndexedIndirect', dispatch='VkCommandBuffer'),
+ Command(name='CmdDispatch', dispatch='VkCommandBuffer'),
+ Command(name='CmdDispatchIndirect', dispatch='VkCommandBuffer'),
+ Command(name='CmdCopyBuffer', dispatch='VkCommandBuffer'),
+ Command(name='CmdCopyImage', dispatch='VkCommandBuffer'),
+ Command(name='CmdBlitImage', dispatch='VkCommandBuffer'),
+ Command(name='CmdCopyBufferToImage', dispatch='VkCommandBuffer'),
+ Command(name='CmdCopyImageToBuffer', dispatch='VkCommandBuffer'),
+ Command(name='CmdUpdateBuffer', dispatch='VkCommandBuffer'),
+ Command(name='CmdFillBuffer', dispatch='VkCommandBuffer'),
+ Command(name='CmdClearColorImage', dispatch='VkCommandBuffer'),
+ Command(name='CmdClearDepthStencilImage', dispatch='VkCommandBuffer'),
+ Command(name='CmdClearAttachments', dispatch='VkCommandBuffer'),
+ Command(name='CmdResolveImage', dispatch='VkCommandBuffer'),
+ Command(name='CmdSetEvent', dispatch='VkCommandBuffer'),
+ Command(name='CmdResetEvent', dispatch='VkCommandBuffer'),
+ Command(name='CmdWaitEvents', dispatch='VkCommandBuffer'),
+ Command(name='CmdPipelineBarrier', dispatch='VkCommandBuffer'),
+ Command(name='CmdBeginQuery', dispatch='VkCommandBuffer'),
+ Command(name='CmdEndQuery', dispatch='VkCommandBuffer'),
+ Command(name='CmdResetQueryPool', dispatch='VkCommandBuffer'),
+ Command(name='CmdWriteTimestamp', dispatch='VkCommandBuffer'),
+ Command(name='CmdCopyQueryPoolResults', dispatch='VkCommandBuffer'),
+ Command(name='CmdPushConstants', dispatch='VkCommandBuffer'),
+ Command(name='CmdBeginRenderPass', dispatch='VkCommandBuffer'),
+ Command(name='CmdNextSubpass', dispatch='VkCommandBuffer'),
+ Command(name='CmdEndRenderPass', dispatch='VkCommandBuffer'),
+ Command(name='CmdExecuteCommands', dispatch='VkCommandBuffer'),
+])
+
+vk_khr_surface = Extension(name='VK_KHR_surface', version=25, guard=None, commands=[
+ Command(name='DestroySurfaceKHR', dispatch='VkInstance'),
+ Command(name='GetPhysicalDeviceSurfaceSupportKHR', dispatch='VkPhysicalDevice'),
+ Command(name='GetPhysicalDeviceSurfaceCapabilitiesKHR', dispatch='VkPhysicalDevice'),
+ Command(name='GetPhysicalDeviceSurfaceFormatsKHR', dispatch='VkPhysicalDevice'),
+ Command(name='GetPhysicalDeviceSurfacePresentModesKHR', dispatch='VkPhysicalDevice'),
+])
+
+vk_khr_swapchain = Extension(name='VK_KHR_swapchain', version=67, guard=None, commands=[
+ Command(name='CreateSwapchainKHR', dispatch='VkDevice'),
+ Command(name='DestroySwapchainKHR', dispatch='VkDevice'),
+ Command(name='GetSwapchainImagesKHR', dispatch='VkDevice'),
+ Command(name='AcquireNextImageKHR', dispatch='VkDevice'),
+ Command(name='QueuePresentKHR', dispatch='VkQueue'),
+])
+
+vk_khr_display = Extension(name='VK_KHR_display', version=21, guard=None, commands=[
+ Command(name='GetPhysicalDeviceDisplayPropertiesKHR', dispatch='VkPhysicalDevice'),
+ Command(name='GetPhysicalDeviceDisplayPlanePropertiesKHR', dispatch='VkPhysicalDevice'),
+ Command(name='GetDisplayPlaneSupportedDisplaysKHR', dispatch='VkPhysicalDevice'),
+ Command(name='GetDisplayModePropertiesKHR', dispatch='VkPhysicalDevice'),
+ Command(name='CreateDisplayModeKHR', dispatch='VkPhysicalDevice'),
+ Command(name='GetDisplayPlaneCapabilitiesKHR', dispatch='VkPhysicalDevice'),
+ Command(name='CreateDisplayPlaneSurfaceKHR', dispatch='VkInstance'),
+])
+
+vk_khr_display_swapchain = Extension(name='VK_KHR_display_swapchain', version=9, guard=None, commands=[
+ Command(name='CreateSharedSwapchainsKHR', dispatch='VkDevice'),
+])
+
+vk_khr_xlib_surface = Extension(name='VK_KHR_xlib_surface', version=6, guard='VK_USE_PLATFORM_XLIB_KHR', commands=[
+ Command(name='CreateXlibSurfaceKHR', dispatch='VkInstance'),
+ Command(name='GetPhysicalDeviceXlibPresentationSupportKHR', dispatch='VkPhysicalDevice'),
+])
+
+vk_khr_xcb_surface = Extension(name='VK_KHR_xcb_surface', version=6, guard='VK_USE_PLATFORM_XCB_KHR', commands=[
+ Command(name='CreateXcbSurfaceKHR', dispatch='VkInstance'),
+ Command(name='GetPhysicalDeviceXcbPresentationSupportKHR', dispatch='VkPhysicalDevice'),
+])
+
+vk_khr_wayland_surface = Extension(name='VK_KHR_wayland_surface', version=5, guard='VK_USE_PLATFORM_WAYLAND_KHR', commands=[
+ Command(name='CreateWaylandSurfaceKHR', dispatch='VkInstance'),
+ Command(name='GetPhysicalDeviceWaylandPresentationSupportKHR', dispatch='VkPhysicalDevice'),
+])
+
+vk_khr_mir_surface = Extension(name='VK_KHR_mir_surface', version=4, guard='VK_USE_PLATFORM_MIR_KHR', commands=[
+ Command(name='CreateMirSurfaceKHR', dispatch='VkInstance'),
+ Command(name='GetPhysicalDeviceMirPresentationSupportKHR', dispatch='VkPhysicalDevice'),
+])
+
+vk_khr_android_surface = Extension(name='VK_KHR_android_surface', version=6, guard='VK_USE_PLATFORM_ANDROID_KHR', commands=[
+ Command(name='CreateAndroidSurfaceKHR', dispatch='VkInstance'),
+])
+
+vk_khr_win32_surface = Extension(name='VK_KHR_win32_surface', version=5, guard='VK_USE_PLATFORM_WIN32_KHR', commands=[
+ Command(name='CreateWin32SurfaceKHR', dispatch='VkInstance'),
+ Command(name='GetPhysicalDeviceWin32PresentationSupportKHR', dispatch='VkPhysicalDevice'),
+])
+
+vk_ext_debug_report = Extension(name='VK_EXT_debug_report', version=1, guard=None, commands=[
+ Command(name='CreateDebugReportCallbackEXT', dispatch='VkInstance'),
+ Command(name='DestroyDebugReportCallbackEXT', dispatch='VkInstance'),
+ Command(name='DebugReportMessageEXT', dispatch='VkInstance'),
+])
+
+extensions = [
+ vk_core,
+ vk_khr_surface,
+ vk_khr_swapchain,
+ vk_khr_display,
+ vk_khr_display_swapchain,
+ vk_khr_xlib_surface,
+ vk_khr_xcb_surface,
+ vk_khr_wayland_surface,
+ vk_khr_mir_surface,
+ vk_khr_android_surface,
+ vk_khr_win32_surface,
+ vk_ext_debug_report,
+]
+
+def generate_header(guard):
+ lines = []
+ lines.append("// This file is generated.")
+ lines.append("#ifndef %s" % guard)
+ lines.append("#define %s" % guard)
+ lines.append("")
+ lines.append("#include <vulkan/vulkan.h>")
+ lines.append("")
+ lines.append("namespace vk {")
+ lines.append("")
+
+ for ext in extensions:
+ if ext.guard:
+ lines.append("#ifdef %s" % ext.guard)
+
+ lines.append("// %s" % ext.name)
+ for cmd in ext.commands:
+ lines.append("extern PFN_vk%s %s;" % (cmd.name, cmd.name))
+
+ if ext.guard:
+ lines.append("#endif")
+ lines.append("")
+
+ lines.append("void init_dispatch_table_top(PFN_vkGetInstanceProcAddr get_instance_proc_addr);")
+ lines.append("void init_dispatch_table_middle(VkInstance instance, bool include_bottom);")
+ lines.append("void init_dispatch_table_bottom(VkInstance instance, VkDevice dev);")
+ lines.append("")
+ lines.append("} // namespace vk")
+ lines.append("")
+ lines.append("#endif // %s" % guard)
+
+ return "\n".join(lines)
+
+def get_proc_addr(dispatchable, cmd, guard=None):
+ if dispatchable == "dev":
+ func = "GetDeviceProcAddr"
+ else:
+ func = "GetInstanceProcAddr"
+
+ c = " %s = reinterpret_cast<PFN_vk%s>(%s(%s, \"vk%s\"));" % \
+ (cmd.name, cmd.name, func, dispatchable, cmd.name)
+
+ if guard:
+ c = ("#ifdef %s\n" % guard) + c + "\n#endif"
+
+ return c
+
+def generate_source(header):
+ lines = []
+ lines.append("// This file is generated.")
+ lines.append("#include \"%s\"" % header)
+ lines.append("")
+ lines.append("namespace vk {")
+ lines.append("")
+
+ commands_by_types = {}
+ get_instance_proc_addr = None
+ get_device_proc_addr = None
+ for ext in extensions:
+ if ext.guard:
+ lines.append("#ifdef %s" % ext.guard)
+
+ for cmd in ext.commands:
+ lines.append("PFN_vk%s %s;" % (cmd.name, cmd.name))
+
+ if cmd.ty not in commands_by_types:
+ commands_by_types[cmd.ty] = []
+ commands_by_types[cmd.ty].append([cmd, ext.guard])
+
+ if cmd.name == "GetInstanceProcAddr":
+ get_instance_proc_addr = cmd
+ elif cmd.name == "GetDeviceProcAddr":
+ get_device_proc_addr = cmd
+
+ if ext.guard:
+ lines.append("#endif")
+ lines.append("")
+
+ lines.append("void init_dispatch_table_top(PFN_vkGetInstanceProcAddr get_instance_proc_addr)")
+ lines.append("{")
+ lines.append(" GetInstanceProcAddr = get_instance_proc_addr;")
+ lines.append("")
+ for cmd, guard in commands_by_types[Command.LOADER]:
+ lines.append(get_proc_addr("VK_NULL_HANDLE", cmd, guard))
+ lines.append("}")
+ lines.append("")
+
+ lines.append("void init_dispatch_table_middle(VkInstance instance, bool include_bottom)")
+ lines.append("{")
+ lines.append(get_proc_addr("instance", get_instance_proc_addr))
+ lines.append("")
+ for cmd, guard in commands_by_types[Command.INSTANCE]:
+ if cmd == get_instance_proc_addr:
+ continue
+ lines.append(get_proc_addr("instance", cmd, guard))
+ lines.append("")
+ lines.append(" if (!include_bottom)")
+ lines.append(" return;")
+ lines.append("")
+ for cmd, guard in commands_by_types[Command.DEVICE]:
+ lines.append(get_proc_addr("instance", cmd, guard))
+ lines.append("}")
+ lines.append("")
+
+ lines.append("void init_dispatch_table_bottom(VkInstance instance, VkDevice dev)")
+ lines.append("{")
+ lines.append(get_proc_addr("instance", get_device_proc_addr))
+ lines.append(get_proc_addr("dev", get_device_proc_addr))
+ lines.append("")
+ for cmd, guard in commands_by_types[Command.DEVICE]:
+ if cmd == get_device_proc_addr:
+ continue
+ lines.append(get_proc_addr("dev", cmd, guard))
+ lines.append("}")
+
+ lines.append("")
+ lines.append("} // namespace vk")
+
+ return "\n".join(lines)
+
+def parse_vulkan_h(filename):
+ extensions = []
+
+ with open(filename, "r") as f:
+ current_ext = None
+ ext_guard = None
+ spec_version = None
+
+ for line in f:
+ line = line.strip();
+
+ if line.startswith("#define VK_API_VERSION"):
+ minor_end = line.rfind(",")
+ minor_begin = line.rfind(",", 0, minor_end) + 1
+ spec_version = int(line[minor_begin:minor_end])
+ # add core
+ current_ext = Extension("VK_core", spec_version)
+ extensions.append(current_ext)
+ elif Command.valid_c_typedef(line):
+ current_ext.add_command(Command.from_c_typedef(line))
+ elif line.startswith("#ifdef VK_USE_PLATFORM"):
+ guard_begin = line.find(" ") + 1
+ ext_guard = line[guard_begin:]
+ elif line.startswith("#define") and "SPEC_VERSION " in line:
+ version_begin = line.rfind(" ") + 1
+ spec_version = int(line[version_begin:])
+ elif line.startswith("#define") and "EXTENSION_NAME " in line:
+ name_end = line.rfind("\"")
+ name_begin = line.rfind("\"", 0, name_end) + 1
+ name = line[name_begin:name_end]
+ # add extension
+ current_ext = Extension(name, spec_version, ext_guard)
+ extensions.append(current_ext)
+ elif ext_guard and line.startswith("#endif") and ext_guard in line:
+ ext_guard = None
+
+ for ext in extensions:
+ print("%s = %s" % (ext.name.lower(), repr(ext)))
+ print("")
+
+ print("extensions = [")
+ for ext in extensions:
+ print(" %s," % ext.name.lower())
+ print("]")
+
+if __name__ == "__main__":
+ if sys.argv[1] == "parse":
+ parse_vulkan_h(sys.argv[2])
+ else:
+ filename = sys.argv[1]
+ base = os.path.basename(filename)
+ contents = []
+
+ if base.endswith(".h"):
+ contents = generate_header(base.replace(".", "_").upper())
+ elif base.endswith(".cpp"):
+ contents = generate_source(base.replace(".cpp", ".h"))
+
+ with open(filename, "w") as f:
+ print(contents, file=f)
diff --git a/demos/smoke/glsl-to-spirv b/demos/smoke/glsl-to-spirv
new file mode 100755
index 00000000..f2104362
--- /dev/null
+++ b/demos/smoke/glsl-to-spirv
@@ -0,0 +1,100 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2016 Google, Inc.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+
+"""Compile GLSL to SPIR-V.
+
+Depends on glslangValidator.
+"""
+
+import os
+import sys
+import subprocess
+import struct
+import re
+
+SPIRV_MAGIC = 0x07230203
+COLUMNS = 4
+INDENT = 4
+
+in_filename = sys.argv[1]
+out_filename = sys.argv[2] if len(sys.argv) > 2 else None
+validator = sys.argv[3] if len(sys.argv) > 3 else \
+ "../../../glslang/build/install/bin/glslangValidator"
+
+def identifierize(s):
+ # translate invalid chars
+ s = re.sub("[^0-9a-zA-Z_]", "_", s)
+ # translate leading digits
+ return re.sub("^[^a-zA-Z_]+", "_", s)
+
+def compile_glsl(filename, tmpfile):
+ # invoke glslangValidator
+ try:
+ args = [validator, "-V", "-H", "-o", tmpfile, filename]
+ output = subprocess.check_output(args, universal_newlines=True)
+ except subprocess.CalledProcessError as e:
+ print(e.output, file=sys.stderr)
+ exit(1)
+
+ # read the temp file into a list of SPIR-V words
+ words = []
+ with open(tmpfile, "rb") as f:
+ data = f.read()
+ assert(len(data) and len(data) % 4 == 0)
+
+ # determine endianness
+ fmt = ("<" if data[0] == (SPIRV_MAGIC & 0xff) else ">") + "I"
+ for i in range(0, len(data), 4):
+ words.append(struct.unpack(fmt, data[i:(i + 4)])[0])
+
+ assert(words[0] == SPIRV_MAGIC)
+
+
+ # remove temp file
+ os.remove(tmpfile)
+
+ return (words, output.rstrip())
+
+base = os.path.basename(in_filename)
+words, comments = compile_glsl(in_filename, base + ".tmp")
+
+literals = []
+for i in range(0, len(words), COLUMNS):
+ columns = ["0x%08x" % word for word in words[i:(i + COLUMNS)]]
+ literals.append(" " * INDENT + ", ".join(columns) + ",")
+
+header = """#include <stdint.h>
+
+#if 0
+%s
+#endif
+
+static const uint32_t %s[%d] = {
+%s
+};
+""" % (comments, identifierize(base), len(words), "\n".join(literals))
+
+if out_filename:
+ with open(out_filename, "w") as f:
+ print(header, end="", file=f)
+else:
+ print(header, end="")