diff options
| author | Tony Barbour <tony@LunarG.com> | 2016-02-25 15:44:10 -0700 |
|---|---|---|
| committer | Tony Barbour <tony@LunarG.com> | 2016-02-26 13:53:07 -0700 |
| commit | 6d366c23f50752c8bc39673416040d89a94a586f (patch) | |
| tree | 7a9493a747ffad8b708fd373ffbee359459ddd66 | |
| parent | 2e4f6dfe4624d966fb4db3c477586bd6b1c2b8e1 (diff) | |
| download | usermoji-6d366c23f50752c8bc39673416040d89a94a586f.tar.xz | |
demos: Add Hologram snapshot as Smoke test/demo
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), ¶ms); + } 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 Binary files differnew file mode 100644 index 00000000..13372aef --- /dev/null +++ b/demos/smoke/android/gradle/wrapper/gradle-wrapper.jar 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="") |
