From 9fef899e42a16d0650bd8684ed30cf645d562932 Mon Sep 17 00:00:00 2001 From: Iago Toral Quiroga Date: Thu, 30 Jun 2022 09:38:25 +0200 Subject: [PATCH 01/36] Fix various cases of image views with incorrect stencil aspect --- examples/deferred/deferred.cpp | 4 +++- examples/hdr/hdr.cpp | 4 +++- examples/multisampling/multisampling.cpp | 4 +++- examples/multiview/multiview.cpp | 4 +++- examples/offscreen/offscreen.cpp | 4 +++- examples/radialblur/radialblur.cpp | 4 +++- examples/renderheadless/renderheadless.cpp | 4 +++- examples/shadowmappingomni/shadowmappingomni.cpp | 4 +++- examples/ssao/ssao.cpp | 4 +++- 9 files changed, 27 insertions(+), 9 deletions(-) diff --git a/examples/deferred/deferred.cpp b/examples/deferred/deferred.cpp index 0994e2f9..7672a46a 100644 --- a/examples/deferred/deferred.cpp +++ b/examples/deferred/deferred.cpp @@ -190,7 +190,9 @@ public: } if (usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { - aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; + aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + if (format >= VK_FORMAT_D16_UNORM_S8_UINT) + aspectMask |=VK_IMAGE_ASPECT_STENCIL_BIT; imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; } diff --git a/examples/hdr/hdr.cpp b/examples/hdr/hdr.cpp index cda5b452..a43180bf 100644 --- a/examples/hdr/hdr.cpp +++ b/examples/hdr/hdr.cpp @@ -314,7 +314,9 @@ public: } if (usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { - aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; + aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + if (format >= VK_FORMAT_D16_UNORM_S8_UINT) + aspectMask |=VK_IMAGE_ASPECT_STENCIL_BIT; imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; } diff --git a/examples/multisampling/multisampling.cpp b/examples/multisampling/multisampling.cpp index 408e18f7..e4e01819 100644 --- a/examples/multisampling/multisampling.cpp +++ b/examples/multisampling/multisampling.cpp @@ -186,7 +186,9 @@ public: viewInfo.components.g = VK_COMPONENT_SWIZZLE_G; viewInfo.components.b = VK_COMPONENT_SWIZZLE_B; viewInfo.components.a = VK_COMPONENT_SWIZZLE_A; - viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; + viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + if (depthFormat >= VK_FORMAT_D16_UNORM_S8_UINT) + viewInfo.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; viewInfo.subresourceRange.levelCount = 1; viewInfo.subresourceRange.layerCount = 1; diff --git a/examples/multiview/multiview.cpp b/examples/multiview/multiview.cpp index a73992f3..13845f59 100644 --- a/examples/multiview/multiview.cpp +++ b/examples/multiview/multiview.cpp @@ -150,7 +150,9 @@ public: depthStencilView.format = depthFormat; depthStencilView.flags = 0; depthStencilView.subresourceRange = {}; - depthStencilView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; + depthStencilView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + if (depthFormat >= VK_FORMAT_D16_UNORM_S8_UINT) + depthStencilView.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; depthStencilView.subresourceRange.baseMipLevel = 0; depthStencilView.subresourceRange.levelCount = 1; depthStencilView.subresourceRange.baseArrayLayer = 0; diff --git a/examples/offscreen/offscreen.cpp b/examples/offscreen/offscreen.cpp index 4ae6cbe7..8c39f7ec 100644 --- a/examples/offscreen/offscreen.cpp +++ b/examples/offscreen/offscreen.cpp @@ -209,7 +209,9 @@ public: depthStencilView.format = fbDepthFormat; depthStencilView.flags = 0; depthStencilView.subresourceRange = {}; - depthStencilView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; + depthStencilView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + if (fbDepthFormat >= VK_FORMAT_D16_UNORM_S8_UINT) + depthStencilView.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; depthStencilView.subresourceRange.baseMipLevel = 0; depthStencilView.subresourceRange.levelCount = 1; depthStencilView.subresourceRange.baseArrayLayer = 0; diff --git a/examples/radialblur/radialblur.cpp b/examples/radialblur/radialblur.cpp index 22daed60..9b54883e 100644 --- a/examples/radialblur/radialblur.cpp +++ b/examples/radialblur/radialblur.cpp @@ -208,7 +208,9 @@ public: depthStencilView.format = fbDepthFormat; depthStencilView.flags = 0; depthStencilView.subresourceRange = {}; - depthStencilView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; + depthStencilView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + if (fbDepthFormat >= VK_FORMAT_D16_UNORM_S8_UINT) + depthStencilView.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; depthStencilView.subresourceRange.baseMipLevel = 0; depthStencilView.subresourceRange.levelCount = 1; depthStencilView.subresourceRange.baseArrayLayer = 0; diff --git a/examples/renderheadless/renderheadless.cpp b/examples/renderheadless/renderheadless.cpp index ba41bf8a..5f56987a 100644 --- a/examples/renderheadless/renderheadless.cpp +++ b/examples/renderheadless/renderheadless.cpp @@ -418,7 +418,9 @@ public: depthStencilView.format = depthFormat; depthStencilView.flags = 0; depthStencilView.subresourceRange = {}; - depthStencilView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; + depthStencilView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + if (depthFormat >= VK_FORMAT_D16_UNORM_S8_UINT) + depthStencilView.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; depthStencilView.subresourceRange.baseMipLevel = 0; depthStencilView.subresourceRange.levelCount = 1; depthStencilView.subresourceRange.baseArrayLayer = 0; diff --git a/examples/shadowmappingomni/shadowmappingomni.cpp b/examples/shadowmappingomni/shadowmappingomni.cpp index 72e82bd5..3835ac01 100644 --- a/examples/shadowmappingomni/shadowmappingomni.cpp +++ b/examples/shadowmappingomni/shadowmappingomni.cpp @@ -291,7 +291,9 @@ public: depthStencilView.format = fbDepthFormat; depthStencilView.flags = 0; depthStencilView.subresourceRange = {}; - depthStencilView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; + depthStencilView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + if (fbDepthFormat >= VK_FORMAT_D16_UNORM_S8_UINT) + depthStencilView.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; depthStencilView.subresourceRange.baseMipLevel = 0; depthStencilView.subresourceRange.levelCount = 1; depthStencilView.subresourceRange.baseArrayLayer = 0; diff --git a/examples/ssao/ssao.cpp b/examples/ssao/ssao.cpp index 92558908..29e73016 100644 --- a/examples/ssao/ssao.cpp +++ b/examples/ssao/ssao.cpp @@ -196,7 +196,9 @@ public: } if (usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { - aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; + aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + if (format >= VK_FORMAT_D16_UNORM_S8_UINT) + aspectMask |=VK_IMAGE_ASPECT_STENCIL_BIT; } assert(aspectMask > 0); From 234973801398b7224aceb0e1978fc14c89404deb Mon Sep 17 00:00:00 2001 From: Stephen Saunders Date: Fri, 10 Sep 2021 01:23:49 -0400 Subject: [PATCH 02/36] Changes to build on macOS and animate frames --- base/VulkanTools.cpp | 3 + base/vulkanexamplebase.h | 6 +- examples/gltfloading/gltfloading.cpp | 4 +- .../gltfscenerendering/gltfscenerendering.h | 4 +- examples/gltfskinning/gltfskinning.h | 2 +- xcode/MVKExample.cpp | 6 +- xcode/MVKExample.h | 1 + xcode/examples.h | 20 +- xcode/examples.xcodeproj/project.pbxproj | 317 +++++++++++++----- xcode/ios/DemoViewController.mm | 5 +- xcode/macos/DemoViewController.mm | 6 +- 11 files changed, 267 insertions(+), 107 deletions(-) diff --git a/base/VulkanTools.cpp b/base/VulkanTools.cpp index 1827ddf5..9659073e 100644 --- a/base/VulkanTools.cpp +++ b/base/VulkanTools.cpp @@ -8,6 +8,8 @@ #include "VulkanTools.h" +#if !(defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK)) +// iOS & macOS: VulkanExampleBase::getAssetPath() implemented externally to allow access to Objective-C components const std::string getAssetPath() { #if defined(VK_USE_PLATFORM_ANDROID_KHR) @@ -18,6 +20,7 @@ const std::string getAssetPath() return "./../data/"; #endif } +#endif namespace vks { diff --git a/base/vulkanexamplebase.h b/base/vulkanexamplebase.h index 14644f6b..2b6eb03c 100644 --- a/base/vulkanexamplebase.h +++ b/base/vulkanexamplebase.h @@ -102,7 +102,7 @@ private: bool resizing = false; void windowResize(); void handleMouseMove(int32_t x, int32_t y); - void nextFrame(); +// void nextFrame(); // SRS - make VulkanExampleBase::nextFrame() public void updateOverlay(); void createPipelineCache(); void createCommandPool(); @@ -401,7 +401,9 @@ public: /** @brief Presents the current image to the swap chain */ void submitFrame(); /** @brief (Virtual) Default image acquire + submission and command buffer submission function */ - virtual void renderFrame(); + void renderFrame(); // SRS - Don't think this needs to be virtual since render() is virtual + /** @brief Draws and advances to the next frame */ + void nextFrame(); // SRS - make VulkanExampleBase::nextFrame() public /** @brief (Virtual) Called when the UI overlay is updating, can be used to add custom elements to the overlay */ virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay); diff --git a/examples/gltfloading/gltfloading.cpp b/examples/gltfloading/gltfloading.cpp index eae2e3da..b71a3edf 100644 --- a/examples/gltfloading/gltfloading.cpp +++ b/examples/gltfloading/gltfloading.cpp @@ -17,7 +17,7 @@ * If you are looking for a complete glTF implementation, check out https://github.com/SaschaWillems/Vulkan-glTF-PBR/ */ -#define TINYGLTF_IMPLEMENTATION +//#define TINYGLTF_IMPLEMENTATION // SRS - Already defined in VulkanglTFModel.cpp #define STB_IMAGE_IMPLEMENTATION #define TINYGLTF_NO_STB_IMAGE_WRITE #ifdef VK_USE_PLATFORM_ANDROID_KHR @@ -739,4 +739,4 @@ public: } }; -VULKAN_EXAMPLE_MAIN() \ No newline at end of file +VULKAN_EXAMPLE_MAIN() diff --git a/examples/gltfscenerendering/gltfscenerendering.h b/examples/gltfscenerendering/gltfscenerendering.h index 8e6b6355..357463fc 100644 --- a/examples/gltfscenerendering/gltfscenerendering.h +++ b/examples/gltfscenerendering/gltfscenerendering.h @@ -12,7 +12,7 @@ * This sample comes with a tutorial, see the README.md in this folder */ -#define TINYGLTF_IMPLEMENTATION +//#define TINYGLTF_IMPLEMENTATION // SRS - Already defined in VulkanglTFModel.cpp #define STB_IMAGE_IMPLEMENTATION #define TINYGLTF_NO_STB_IMAGE_WRITE #define TINYGLTF_NO_STB_IMAGE @@ -163,4 +163,4 @@ public: void prepare(); virtual void render(); virtual void OnUpdateUIOverlay(vks::UIOverlay* overlay); -}; \ No newline at end of file +}; diff --git a/examples/gltfskinning/gltfskinning.h b/examples/gltfskinning/gltfskinning.h index 9423c01c..e60317fc 100644 --- a/examples/gltfskinning/gltfskinning.h +++ b/examples/gltfskinning/gltfskinning.h @@ -27,7 +27,7 @@ #include #include -#define TINYGLTF_IMPLEMENTATION +//#define TINYGLTF_IMPLEMENTATION // SRS - Already defined in VulkanglTFModel.cpp #define STB_IMAGE_IMPLEMENTATION #define TINYGLTF_NO_STB_IMAGE_WRITE #ifdef VK_USE_PLATFORM_ANDROID_KHR diff --git a/xcode/MVKExample.cpp b/xcode/MVKExample.cpp index 6db1c1cd..5b00eacc 100644 --- a/xcode/MVKExample.cpp +++ b/xcode/MVKExample.cpp @@ -13,6 +13,10 @@ void MVKExample::renderFrame() { _vulkanExample->renderFrame(); } +void MVKExample::nextFrame() { // SRS - expose VulkanExampleBase::nextFrame() to DemoViewController + _vulkanExample->nextFrame(); +} + void MVKExample::keyPressed(uint32_t keyCode) { _vulkanExample->keyPressed(keyCode); } @@ -21,7 +25,7 @@ MVKExample::MVKExample(void* view) { _vulkanExample = new VulkanExample(); _vulkanExample->initVulkan(); _vulkanExample->setupWindow(view); - _vulkanExample->initSwapchain(); +// _vulkanExample->initSwapchain(); // SRS - initSwapchain() is now part of VulkanExampleBase::prepare() _vulkanExample->prepare(); } diff --git a/xcode/MVKExample.h b/xcode/MVKExample.h index 93d921ec..dd03e713 100644 --- a/xcode/MVKExample.h +++ b/xcode/MVKExample.h @@ -14,6 +14,7 @@ class MVKExample { public: void renderFrame(); + void nextFrame(); // SRS - expose VulkanExampleBase::nextFrame() to DemoViewController void keyPressed(uint32_t keyCode); MVKExample(void* view); diff --git a/xcode/examples.h b/xcode/examples.h index 20b7ab89..94c7f59a 100644 --- a/xcode/examples.h +++ b/xcode/examples.h @@ -27,7 +27,7 @@ // In the list below, the comments indicate entries that, // under certain conditions, that may not run as expected. -#define MVK_vulkanscene +#define MVK_gltfskinning // BASICS @@ -50,9 +50,9 @@ # include "../examples/texturearray/texturearray.cpp" #endif -#ifdef MVK_mesh -# include "../examples/mesh/mesh.cpp" -#endif +//#ifdef MVK_mesh +//# include "../examples/mesh/mesh.cpp" +//#endif #ifdef MVK_dynamicuniformbuffer # include "../examples/dynamicuniformbuffer/dynamicuniformbuffer.cpp" @@ -90,8 +90,8 @@ # include "../examples/multithreading/multithreading.cpp" #endif -#ifdef MVK_scenerendering -# include "../examples/scenerendering/scenerendering.cpp" +#ifdef MVK_gltfscenerendering +# include "../examples/gltfscenerendering/gltfscenerendering.cpp" #endif #ifdef MVK_instancing @@ -178,6 +178,7 @@ #ifdef MVK_gears # include "../examples/gears/gears.cpp" +# include "../examples/gears/vulkangear.cpp" #endif #ifdef MVK_distancefieldfonts @@ -188,3 +189,10 @@ # include "../examples/vulkanscene/vulkanscene.cpp" #endif +#ifdef MVK_gltfloading +# include "../examples/gltfloading/gltfloading.cpp" +#endif + +#ifdef MVK_gltfskinning +# include "../examples/gltfskinning/gltfskinning.cpp" +#endif diff --git a/xcode/examples.xcodeproj/project.pbxproj b/xcode/examples.xcodeproj/project.pbxproj index ba6eec40..d4091e0d 100644 --- a/xcode/examples.xcodeproj/project.pbxproj +++ b/xcode/examples.xcodeproj/project.pbxproj @@ -16,7 +16,7 @@ A9532B761EF99894000A09E2 /* libMoltenVK.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = A9532B751EF99894000A09E2 /* libMoltenVK.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; A9532B771EF9991A000A09E2 /* libMoltenVK.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = A9532B751EF99894000A09E2 /* libMoltenVK.dylib */; }; A9532B781EF99937000A09E2 /* libMoltenVK.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = A9581BAB1EEB64EC00247309 /* libMoltenVK.dylib */; }; - A9581BA81EEB648C00247309 /* libzlibstatic.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A9581BA71EEB648C00247309 /* libzlibstatic.a */; }; + A9581BA81EEB648C00247309 /* (null) in Frameworks */ = {isa = PBXBuildFile; }; A9581BAC1EEB64EC00247309 /* libMoltenVK.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = A9581BAB1EEB64EC00247309 /* libMoltenVK.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; A98703D91E9D382A0066959C /* data in Resources */ = {isa = PBXBuildFile; fileRef = A98703D81E9D382A0066959C /* data */; }; A98703DA1E9D382A0066959C /* data in Resources */ = {isa = PBXBuildFile; fileRef = A98703D81E9D382A0066959C /* data */; }; @@ -34,16 +34,53 @@ A9B67B911C3AAEA200373FFD /* macOS.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A9B67B8B1C3AAEA200373FFD /* macOS.xcassets */; }; A9BC9B1C1EE8421F00384233 /* MVKExample.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9BC9B1A1EE8421F00384233 /* MVKExample.cpp */; }; A9BC9B1D1EE8421F00384233 /* MVKExample.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9BC9B1A1EE8421F00384233 /* MVKExample.cpp */; }; + AA54A1B426E5274500485C4A /* VulkanBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA54A1B226E5274500485C4A /* VulkanBuffer.cpp */; }; + AA54A1B526E5274500485C4A /* VulkanBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA54A1B226E5274500485C4A /* VulkanBuffer.cpp */; }; + AA54A1B826E5275300485C4A /* VulkanDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA54A1B626E5275300485C4A /* VulkanDevice.cpp */; }; + AA54A1B926E5275300485C4A /* VulkanDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA54A1B626E5275300485C4A /* VulkanDevice.cpp */; }; + AA54A1BC26E5276000485C4A /* VulkanglTFModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA54A1BA26E5276000485C4A /* VulkanglTFModel.cpp */; }; + AA54A1BD26E5276000485C4A /* VulkanglTFModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA54A1BA26E5276000485C4A /* VulkanglTFModel.cpp */; }; + AA54A1C026E5276C00485C4A /* VulkanSwapChain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA54A1BF26E5276C00485C4A /* VulkanSwapChain.cpp */; }; + AA54A1C126E5276C00485C4A /* VulkanSwapChain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA54A1BF26E5276C00485C4A /* VulkanSwapChain.cpp */; }; + AA54A1C426E5277600485C4A /* VulkanTexture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA54A1C326E5277600485C4A /* VulkanTexture.cpp */; }; + AA54A1C526E5277600485C4A /* VulkanTexture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA54A1C326E5277600485C4A /* VulkanTexture.cpp */; }; + AA54A6B826E52CE300485C4A /* memstream.c in Sources */ = {isa = PBXBuildFile; fileRef = AA54A1DD26E52CE100485C4A /* memstream.c */; }; + AA54A6B926E52CE300485C4A /* memstream.c in Sources */ = {isa = PBXBuildFile; fileRef = AA54A1DD26E52CE100485C4A /* memstream.c */; }; + AA54A6BA26E52CE300485C4A /* vk_funclist.inl in Resources */ = {isa = PBXBuildFile; fileRef = AA54A1DE26E52CE100485C4A /* vk_funclist.inl */; }; + AA54A6BB26E52CE300485C4A /* vk_funclist.inl in Resources */ = {isa = PBXBuildFile; fileRef = AA54A1DE26E52CE100485C4A /* vk_funclist.inl */; }; + AA54A6BC26E52CE300485C4A /* etcdec.cxx in Sources */ = {isa = PBXBuildFile; fileRef = AA54A1E026E52CE100485C4A /* etcdec.cxx */; }; + AA54A6BD26E52CE300485C4A /* etcdec.cxx in Sources */ = {isa = PBXBuildFile; fileRef = AA54A1E026E52CE100485C4A /* etcdec.cxx */; }; + AA54A6BE26E52CE300485C4A /* checkheader.c in Sources */ = {isa = PBXBuildFile; fileRef = AA54A1E126E52CE100485C4A /* checkheader.c */; }; + AA54A6BF26E52CE300485C4A /* checkheader.c in Sources */ = {isa = PBXBuildFile; fileRef = AA54A1E126E52CE100485C4A /* checkheader.c */; }; + AA54A6C026E52CE300485C4A /* errstr.c in Sources */ = {isa = PBXBuildFile; fileRef = AA54A1E226E52CE100485C4A /* errstr.c */; }; + AA54A6C126E52CE300485C4A /* errstr.c in Sources */ = {isa = PBXBuildFile; fileRef = AA54A1E226E52CE100485C4A /* errstr.c */; }; + AA54A6C226E52CE300485C4A /* writer.c in Sources */ = {isa = PBXBuildFile; fileRef = AA54A1E326E52CE100485C4A /* writer.c */; }; + AA54A6C326E52CE300485C4A /* writer.c in Sources */ = {isa = PBXBuildFile; fileRef = AA54A1E326E52CE100485C4A /* writer.c */; }; + AA54A6C426E52CE300485C4A /* filestream.c in Sources */ = {isa = PBXBuildFile; fileRef = AA54A1E426E52CE100485C4A /* filestream.c */; }; + AA54A6C526E52CE300485C4A /* filestream.c in Sources */ = {isa = PBXBuildFile; fileRef = AA54A1E426E52CE100485C4A /* filestream.c */; }; + AA54A6C626E52CE300485C4A /* mainpage.md in Resources */ = {isa = PBXBuildFile; fileRef = AA54A1E626E52CE100485C4A /* mainpage.md */; }; + AA54A6C726E52CE300485C4A /* mainpage.md in Resources */ = {isa = PBXBuildFile; fileRef = AA54A1E626E52CE100485C4A /* mainpage.md */; }; + AA54A6CA26E52CE300485C4A /* texture.c in Sources */ = {isa = PBXBuildFile; fileRef = AA54A1EA26E52CE100485C4A /* texture.c */; }; + AA54A6CB26E52CE300485C4A /* texture.c in Sources */ = {isa = PBXBuildFile; fileRef = AA54A1EA26E52CE100485C4A /* texture.c */; }; + AA54A6CC26E52CE300485C4A /* hashlist.c in Sources */ = {isa = PBXBuildFile; fileRef = AA54A1ED26E52CE100485C4A /* hashlist.c */; }; + AA54A6CD26E52CE400485C4A /* hashlist.c in Sources */ = {isa = PBXBuildFile; fileRef = AA54A1ED26E52CE100485C4A /* hashlist.c */; }; + AA54A6CE26E52CE400485C4A /* vk_funcs.c in Sources */ = {isa = PBXBuildFile; fileRef = AA54A1EE26E52CE100485C4A /* vk_funcs.c */; }; + AA54A6CF26E52CE400485C4A /* vk_funcs.c in Sources */ = {isa = PBXBuildFile; fileRef = AA54A1EE26E52CE100485C4A /* vk_funcs.c */; }; + AA54A6D226E52CE400485C4A /* hashtable.c in Sources */ = {isa = PBXBuildFile; fileRef = AA54A1F626E52CE100485C4A /* hashtable.c */; }; + AA54A6D326E52CE400485C4A /* hashtable.c in Sources */ = {isa = PBXBuildFile; fileRef = AA54A1F626E52CE100485C4A /* hashtable.c */; }; + AA54A6D826E52CE400485C4A /* swap.c in Sources */ = {isa = PBXBuildFile; fileRef = AA54A1F926E52CE100485C4A /* swap.c */; }; + AA54A6D926E52CE400485C4A /* swap.c in Sources */ = {isa = PBXBuildFile; fileRef = AA54A1F926E52CE100485C4A /* swap.c */; }; + AA54A6DE26E52CE400485C4A /* imgui_widgets.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA54A20426E52CE100485C4A /* imgui_widgets.cpp */; }; + AA54A6DF26E52CE400485C4A /* imgui_widgets.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA54A20426E52CE100485C4A /* imgui_widgets.cpp */; }; + AA54A6E026E52CE400485C4A /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA54A20626E52CE100485C4A /* imgui.cpp */; }; + AA54A6E126E52CE400485C4A /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA54A20626E52CE100485C4A /* imgui.cpp */; }; + AA54A6E226E52CE400485C4A /* LICENSE.txt in Resources */ = {isa = PBXBuildFile; fileRef = AA54A20926E52CE100485C4A /* LICENSE.txt */; }; + AA54A6E326E52CE400485C4A /* LICENSE.txt in Resources */ = {isa = PBXBuildFile; fileRef = AA54A20926E52CE100485C4A /* LICENSE.txt */; }; + AA54A6E426E52CE400485C4A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA54A20A26E52CE100485C4A /* imgui_demo.cpp */; }; + AA54A6E526E52CE400485C4A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA54A20A26E52CE100485C4A /* imgui_demo.cpp */; }; + AA54A6E626E52CE400485C4A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA54A20B26E52CE100485C4A /* imgui_draw.cpp */; }; + AA54A6E726E52CE400485C4A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA54A20B26E52CE100485C4A /* imgui_draw.cpp */; }; C9788FD52044D78D00AB0892 /* VulkanAndroid.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C9788FD32044D78D00AB0892 /* VulkanAndroid.cpp */; }; - C9A79EF12045045E00696219 /* stb_textedit.h in Sources */ = {isa = PBXBuildFile; fileRef = C9A79EE82045045D00696219 /* stb_textedit.h */; }; - C9A79EF22045045E00696219 /* imconfig.h in Sources */ = {isa = PBXBuildFile; fileRef = C9A79EE92045045D00696219 /* imconfig.h */; }; - C9A79EF32045045E00696219 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C9A79EEA2045045D00696219 /* imgui_demo.cpp */; }; - C9A79EF42045045E00696219 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C9A79EEB2045045D00696219 /* imgui_draw.cpp */; }; - C9A79EF52045045E00696219 /* imgui_internal.h in Sources */ = {isa = PBXBuildFile; fileRef = C9A79EEC2045045E00696219 /* imgui_internal.h */; }; - C9A79EF62045045E00696219 /* stb_rect_pack.h in Sources */ = {isa = PBXBuildFile; fileRef = C9A79EED2045045E00696219 /* stb_rect_pack.h */; }; - C9A79EF72045045E00696219 /* imgui.h in Sources */ = {isa = PBXBuildFile; fileRef = C9A79EEE2045045E00696219 /* imgui.h */; }; - C9A79EF82045045E00696219 /* stb_truetype.h in Sources */ = {isa = PBXBuildFile; fileRef = C9A79EEF2045045E00696219 /* stb_truetype.h */; }; - C9A79EF92045045E00696219 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C9A79EF02045045E00696219 /* imgui.cpp */; }; C9A79EFC204504E000696219 /* VulkanUIOverlay.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C9A79EFB204504E000696219 /* VulkanUIOverlay.cpp */; }; C9A79EFD2045051D00696219 /* VulkanUIOverlay.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C9A79EFB204504E000696219 /* VulkanUIOverlay.cpp */; }; C9A79EFE2045051D00696219 /* VulkanUIOverlay.h in Sources */ = {isa = PBXBuildFile; fileRef = C9A79EFA204504E000696219 /* VulkanUIOverlay.h */; }; @@ -78,44 +115,35 @@ 1D6058910D05DD3D006BFB54 /* examples.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = examples.app; sourceTree = BUILT_PRODUCTS_DIR; }; 2D500B990D5A79CF00DBA0E3 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; A92F37071C7E1B2B008F8BC9 /* examples.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = examples.h; sourceTree = ""; }; - A94A67231B7BDE9B00F6D7C4 /* MetalGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalGL.framework; path = ../../MetalGL/macOS/MetalGL.framework; sourceTree = ""; }; - A94A67241B7BDE9B00F6D7C4 /* MetalGLShaderConverter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalGLShaderConverter.framework; path = ../../MetalGLShaderConverter/macOS/MetalGLShaderConverter.framework; sourceTree = ""; }; A951FF001E9C349000FA9144 /* camera.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = camera.hpp; sourceTree = ""; }; A951FF011E9C349000FA9144 /* frustum.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = frustum.hpp; sourceTree = ""; }; A951FF021E9C349000FA9144 /* keycodes.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = keycodes.hpp; sourceTree = ""; }; A951FF031E9C349000FA9144 /* threadpool.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = threadpool.hpp; sourceTree = ""; }; - A951FF061E9C349000FA9144 /* VulkanBuffer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = VulkanBuffer.hpp; sourceTree = ""; }; A951FF071E9C349000FA9144 /* VulkanDebug.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VulkanDebug.cpp; sourceTree = ""; }; A951FF081E9C349000FA9144 /* VulkanDebug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VulkanDebug.h; sourceTree = ""; }; - A951FF091E9C349000FA9144 /* VulkanDevice.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = VulkanDevice.hpp; sourceTree = ""; }; A951FF0A1E9C349000FA9144 /* vulkanexamplebase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vulkanexamplebase.cpp; sourceTree = ""; }; A951FF0B1E9C349000FA9144 /* vulkanexamplebase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vulkanexamplebase.h; sourceTree = ""; }; A951FF0C1E9C349000FA9144 /* VulkanFrameBuffer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = VulkanFrameBuffer.hpp; sourceTree = ""; }; A951FF0D1E9C349000FA9144 /* VulkanHeightmap.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = VulkanHeightmap.hpp; sourceTree = ""; }; A951FF0E1E9C349000FA9144 /* VulkanInitializers.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = VulkanInitializers.hpp; sourceTree = ""; }; - A951FF0F1E9C349000FA9144 /* VulkanModel.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = VulkanModel.hpp; sourceTree = ""; }; - A951FF101E9C349000FA9144 /* VulkanSwapChain.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = VulkanSwapChain.hpp; sourceTree = ""; }; - A951FF121E9C349000FA9144 /* VulkanTexture.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = VulkanTexture.hpp; sourceTree = ""; }; A951FF131E9C349000FA9144 /* VulkanTools.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VulkanTools.cpp; sourceTree = ""; }; A951FF141E9C349000FA9144 /* VulkanTools.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VulkanTools.h; sourceTree = ""; }; - A9532B751EF99894000A09E2 /* libMoltenVK.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libMoltenVK.dylib; path = MoltenVK/iOS/libMoltenVK.dylib; sourceTree = ""; }; - A9581BAB1EEB64EC00247309 /* libMoltenVK.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libMoltenVK.dylib; path = MoltenVK/macOS/libMoltenVK.dylib; sourceTree = ""; }; + A9532B751EF99894000A09E2 /* libMoltenVK.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libMoltenVK.dylib; path = MoltenVK/dylib/iOS/libMoltenVK.dylib; sourceTree = ""; }; + A9581BAB1EEB64EC00247309 /* libMoltenVK.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libMoltenVK.dylib; path = MoltenVK/dylib/macOS/libMoltenVK.dylib; sourceTree = ""; }; A977BCFE1B66BB010067E5BF /* examples.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = examples.app; sourceTree = BUILT_PRODUCTS_DIR; }; - A977BD211B67186B0067E5BF /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/AppKit.framework; sourceTree = DEVELOPER_DIR; }; - A977BD221B67186B0067E5BF /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/CoreGraphics.framework; sourceTree = DEVELOPER_DIR; }; - A977BD231B67186B0067E5BF /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; - A977BD251B67186B0067E5BF /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/Metal.framework; sourceTree = DEVELOPER_DIR; }; - A977BD261B67186B0067E5BF /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/QuartzCore.framework; sourceTree = DEVELOPER_DIR; }; + A977BD211B67186B0067E5BF /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; + A977BD221B67186B0067E5BF /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + A977BD231B67186B0067E5BF /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + A977BD251B67186B0067E5BF /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; }; + A977BD261B67186B0067E5BF /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; A98703D81E9D382A0066959C /* data */ = {isa = PBXFileReference; lastKnownFileType = folder; name = data; path = ../data; sourceTree = ""; }; A9A222171B5D69F40050A5F9 /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; }; - A9B5D09B1CF8830B00D7CBDD /* libc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; }; A9B67B6B1C3AAE9800373FFD /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; A9B67B6C1C3AAE9800373FFD /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; A9B67B6E1C3AAE9800373FFD /* DemoViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DemoViewController.h; sourceTree = ""; }; A9B67B6F1C3AAE9800373FFD /* DemoViewController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DemoViewController.mm; sourceTree = ""; }; A9B67B701C3AAE9800373FFD /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; A9B67B711C3AAE9800373FFD /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - A9B67B721C3AAE9800373FFD /* Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Prefix.pch; sourceTree = ""; }; A9B67B741C3AAE9800373FFD /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; A9B67B751C3AAE9800373FFD /* Default~ipad.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default~ipad.png"; sourceTree = ""; }; A9B67B761C3AAE9800373FFD /* Icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Icon.png; sourceTree = ""; }; @@ -126,26 +154,56 @@ A9B67B851C3AAEA200373FFD /* DemoViewController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DemoViewController.mm; sourceTree = ""; }; A9B67B861C3AAEA200373FFD /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; A9B67B871C3AAEA200373FFD /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - A9B67B881C3AAEA200373FFD /* Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Prefix.pch; sourceTree = ""; }; A9B67B8A1C3AAEA200373FFD /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; }; A9B67B8B1C3AAEA200373FFD /* macOS.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = macOS.xcassets; sourceTree = ""; }; A9B6B7641C0F795D00A9E33A /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = System/Library/Frameworks/CoreAudio.framework; sourceTree = SDKROOT; }; A9BC9B1A1EE8421F00384233 /* MVKExample.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MVKExample.cpp; sourceTree = ""; }; A9BC9B1B1EE8421F00384233 /* MVKExample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVKExample.h; sourceTree = ""; }; A9CDEA271B6A782C00F7B008 /* GLKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GLKit.framework; path = System/Library/Frameworks/GLKit.framework; sourceTree = SDKROOT; }; - A9E264761B671B0A00FE691A /* libc++.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libc++.dylib"; path = "Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/lib/libc++.dylib"; sourceTree = DEVELOPER_DIR; }; + AA54A1B226E5274500485C4A /* VulkanBuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VulkanBuffer.cpp; sourceTree = ""; }; + AA54A1B326E5274500485C4A /* VulkanBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VulkanBuffer.h; sourceTree = ""; }; + AA54A1B626E5275300485C4A /* VulkanDevice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VulkanDevice.cpp; sourceTree = ""; }; + AA54A1B726E5275300485C4A /* VulkanDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VulkanDevice.h; sourceTree = ""; }; + AA54A1BA26E5276000485C4A /* VulkanglTFModel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VulkanglTFModel.cpp; sourceTree = ""; }; + AA54A1BB26E5276000485C4A /* VulkanglTFModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VulkanglTFModel.h; sourceTree = ""; }; + AA54A1BE26E5276C00485C4A /* VulkanSwapChain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VulkanSwapChain.h; sourceTree = ""; }; + AA54A1BF26E5276C00485C4A /* VulkanSwapChain.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VulkanSwapChain.cpp; sourceTree = ""; }; + AA54A1C226E5277600485C4A /* VulkanTexture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VulkanTexture.h; sourceTree = ""; }; + AA54A1C326E5277600485C4A /* VulkanTexture.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VulkanTexture.cpp; sourceTree = ""; }; + AA54A1DD26E52CE100485C4A /* memstream.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = memstream.c; sourceTree = ""; }; + AA54A1DE26E52CE100485C4A /* vk_funclist.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = vk_funclist.inl; sourceTree = ""; }; + AA54A1E026E52CE100485C4A /* etcdec.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = etcdec.cxx; sourceTree = ""; }; + AA54A1E126E52CE100485C4A /* checkheader.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = checkheader.c; sourceTree = ""; }; + AA54A1E226E52CE100485C4A /* errstr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = errstr.c; sourceTree = ""; }; + AA54A1E326E52CE100485C4A /* writer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = writer.c; sourceTree = ""; }; + AA54A1E426E52CE100485C4A /* filestream.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = filestream.c; sourceTree = ""; }; + AA54A1E626E52CE100485C4A /* mainpage.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = mainpage.md; sourceTree = ""; }; + AA54A1E926E52CE100485C4A /* vk_format.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vk_format.h; sourceTree = ""; }; + AA54A1EA26E52CE100485C4A /* texture.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = texture.c; sourceTree = ""; }; + AA54A1EB26E52CE100485C4A /* ktxint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ktxint.h; sourceTree = ""; }; + AA54A1EC26E52CE100485C4A /* stream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stream.h; sourceTree = ""; }; + AA54A1ED26E52CE100485C4A /* hashlist.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hashlist.c; sourceTree = ""; }; + AA54A1EE26E52CE100485C4A /* vk_funcs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vk_funcs.c; sourceTree = ""; }; + AA54A1F026E52CE100485C4A /* uthash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uthash.h; sourceTree = ""; }; + AA54A1F226E52CE100485C4A /* memstream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = memstream.h; sourceTree = ""; }; + AA54A1F526E52CE100485C4A /* filestream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = filestream.h; sourceTree = ""; }; + AA54A1F626E52CE100485C4A /* hashtable.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hashtable.c; sourceTree = ""; }; + AA54A1F926E52CE100485C4A /* swap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = swap.c; sourceTree = ""; }; + AA54A1FB26E52CE100485C4A /* vk_funcs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vk_funcs.h; sourceTree = ""; }; + AA54A20126E52CE100485C4A /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui.h; sourceTree = ""; }; + AA54A20226E52CE100485C4A /* imstb_textedit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imstb_textedit.h; sourceTree = ""; }; + AA54A20326E52CE100485C4A /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imconfig.h; sourceTree = ""; }; + AA54A20426E52CE100485C4A /* imgui_widgets.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_widgets.cpp; sourceTree = ""; }; + AA54A20526E52CE100485C4A /* imstb_truetype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imstb_truetype.h; sourceTree = ""; }; + AA54A20626E52CE100485C4A /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui.cpp; sourceTree = ""; }; + AA54A20726E52CE100485C4A /* imgui_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_internal.h; sourceTree = ""; }; + AA54A20826E52CE100485C4A /* imstb_rectpack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imstb_rectpack.h; sourceTree = ""; }; + AA54A20926E52CE100485C4A /* LICENSE.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE.txt; sourceTree = ""; }; + AA54A20A26E52CE100485C4A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_demo.cpp; sourceTree = ""; }; + AA54A20B26E52CE100485C4A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_draw.cpp; sourceTree = ""; }; C9788FD02044D78D00AB0892 /* benchmark.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = benchmark.hpp; sourceTree = ""; }; C9788FD22044D78D00AB0892 /* VulkanAndroid.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VulkanAndroid.h; sourceTree = ""; }; C9788FD32044D78D00AB0892 /* VulkanAndroid.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VulkanAndroid.cpp; sourceTree = ""; }; - C9A79EE82045045D00696219 /* stb_textedit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = stb_textedit.h; path = ../external/imgui/stb_textedit.h; sourceTree = ""; }; - C9A79EE92045045D00696219 /* imconfig.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../external/imgui/imconfig.h; sourceTree = ""; }; - C9A79EEA2045045D00696219 /* imgui_demo.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../external/imgui/imgui_demo.cpp; sourceTree = ""; }; - C9A79EEB2045045D00696219 /* imgui_draw.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../external/imgui/imgui_draw.cpp; sourceTree = ""; }; - C9A79EEC2045045E00696219 /* imgui_internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = imgui_internal.h; path = ../external/imgui/imgui_internal.h; sourceTree = ""; }; - C9A79EED2045045E00696219 /* stb_rect_pack.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = stb_rect_pack.h; path = ../external/imgui/stb_rect_pack.h; sourceTree = ""; }; - C9A79EEE2045045E00696219 /* imgui.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../external/imgui/imgui.h; sourceTree = ""; }; - C9A79EEF2045045E00696219 /* stb_truetype.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = stb_truetype.h; path = ../external/imgui/stb_truetype.h; sourceTree = ""; }; - C9A79EF02045045E00696219 /* imgui.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../external/imgui/imgui.cpp; sourceTree = ""; }; C9A79EFA204504E000696219 /* VulkanUIOverlay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VulkanUIOverlay.h; sourceTree = ""; }; C9A79EFB204504E000696219 /* VulkanUIOverlay.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VulkanUIOverlay.cpp; sourceTree = ""; }; /* End PBXFileReference section */ @@ -156,7 +214,7 @@ buildActionMask = 2147483647; files = ( A9532B771EF9991A000A09E2 /* libMoltenVK.dylib in Frameworks */, - A9581BA81EEB648C00247309 /* libzlibstatic.a in Frameworks */, + A9581BA81EEB648C00247309 /* (null) in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -183,19 +241,11 @@ 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { isa = PBXGroup; children = ( - C9A79EE92045045D00696219 /* imconfig.h */, - C9A79EEA2045045D00696219 /* imgui_demo.cpp */, - C9A79EEB2045045D00696219 /* imgui_draw.cpp */, - C9A79EEC2045045E00696219 /* imgui_internal.h */, - C9A79EF02045045E00696219 /* imgui.cpp */, - C9A79EEE2045045E00696219 /* imgui.h */, - C9A79EED2045045E00696219 /* stb_rect_pack.h */, - C9A79EE82045045D00696219 /* stb_textedit.h */, - C9A79EEF2045045E00696219 /* stb_truetype.h */, A92F37071C7E1B2B008F8BC9 /* examples.h */, A9BC9B1B1EE8421F00384233 /* MVKExample.h */, A9BC9B1A1EE8421F00384233 /* MVKExample.cpp */, A951FEFF1E9C349000FA9144 /* base */, + AA54A1CF26E52CE100485C4A /* external */, A98703D81E9D382A0066959C /* data */, A9B67B6A1C3AAE9800373FFD /* iOS */, A9B67B811C3AAEA200373FFD /* macOS */, @@ -210,8 +260,6 @@ children = ( A9581BAB1EEB64EC00247309 /* libMoltenVK.dylib */, A9532B751EF99894000A09E2 /* libMoltenVK.dylib */, - A9581BA71EEB648C00247309 /* libzlibstatic.a */, - A9B5D09B1CF8830B00D7CBDD /* libc++.tbd */, A9B6B7641C0F795D00A9E33A /* CoreAudio.framework */, A9ADEC601B6EC2EB00DBA48C /* iOS */, A9ADEC611B6EC2F300DBA48C /* macOS */, @@ -231,18 +279,23 @@ A951FF011E9C349000FA9144 /* frustum.hpp */, A951FF021E9C349000FA9144 /* keycodes.hpp */, A951FF031E9C349000FA9144 /* threadpool.hpp */, - A951FF061E9C349000FA9144 /* VulkanBuffer.hpp */, + AA54A1B226E5274500485C4A /* VulkanBuffer.cpp */, + AA54A1B326E5274500485C4A /* VulkanBuffer.h */, A951FF071E9C349000FA9144 /* VulkanDebug.cpp */, A951FF081E9C349000FA9144 /* VulkanDebug.h */, - A951FF091E9C349000FA9144 /* VulkanDevice.hpp */, + AA54A1B626E5275300485C4A /* VulkanDevice.cpp */, + AA54A1B726E5275300485C4A /* VulkanDevice.h */, A951FF0A1E9C349000FA9144 /* vulkanexamplebase.cpp */, A951FF0B1E9C349000FA9144 /* vulkanexamplebase.h */, A951FF0C1E9C349000FA9144 /* VulkanFrameBuffer.hpp */, A951FF0D1E9C349000FA9144 /* VulkanHeightmap.hpp */, A951FF0E1E9C349000FA9144 /* VulkanInitializers.hpp */, - A951FF0F1E9C349000FA9144 /* VulkanModel.hpp */, - A951FF101E9C349000FA9144 /* VulkanSwapChain.hpp */, - A951FF121E9C349000FA9144 /* VulkanTexture.hpp */, + AA54A1BA26E5276000485C4A /* VulkanglTFModel.cpp */, + AA54A1BB26E5276000485C4A /* VulkanglTFModel.h */, + AA54A1BF26E5276C00485C4A /* VulkanSwapChain.cpp */, + AA54A1BE26E5276C00485C4A /* VulkanSwapChain.h */, + AA54A1C326E5277600485C4A /* VulkanTexture.cpp */, + AA54A1C226E5277600485C4A /* VulkanTexture.h */, A951FF131E9C349000FA9144 /* VulkanTools.cpp */, A951FF141E9C349000FA9144 /* VulkanTools.h */, ); @@ -265,14 +318,11 @@ A9ADEC611B6EC2F300DBA48C /* macOS */ = { isa = PBXGroup; children = ( - A94A67231B7BDE9B00F6D7C4 /* MetalGL.framework */, - A94A67241B7BDE9B00F6D7C4 /* MetalGLShaderConverter.framework */, - A9E264761B671B0A00FE691A /* libc++.dylib */, A977BD251B67186B0067E5BF /* Metal.framework */, - A977BD261B67186B0067E5BF /* QuartzCore.framework */, - A977BD211B67186B0067E5BF /* AppKit.framework */, A977BD221B67186B0067E5BF /* CoreGraphics.framework */, + A977BD261B67186B0067E5BF /* QuartzCore.framework */, A977BD231B67186B0067E5BF /* Foundation.framework */, + A977BD211B67186B0067E5BF /* AppKit.framework */, ); name = macOS; sourceTree = ""; @@ -286,7 +336,6 @@ A9B67B6F1C3AAE9800373FFD /* DemoViewController.mm */, A9B67B701C3AAE9800373FFD /* Info.plist */, A9B67B711C3AAE9800373FFD /* main.m */, - A9B67B721C3AAE9800373FFD /* Prefix.pch */, A9B67B731C3AAE9800373FFD /* Resources */, ); path = iOS; @@ -312,7 +361,6 @@ A9B67B851C3AAEA200373FFD /* DemoViewController.mm */, A9B67B861C3AAEA200373FFD /* Info.plist */, A9B67B871C3AAEA200373FFD /* main.m */, - A9B67B881C3AAEA200373FFD /* Prefix.pch */, A9B67B891C3AAEA200373FFD /* Resources */, ); path = macOS; @@ -327,6 +375,69 @@ path = Resources; sourceTree = ""; }; + AA54A1CF26E52CE100485C4A /* external */ = { + isa = PBXGroup; + children = ( + AA54A1D626E52CE100485C4A /* ktx */, + AA54A20026E52CE100485C4A /* imgui */, + ); + name = external; + path = ../external; + sourceTree = ""; + }; + AA54A1D626E52CE100485C4A /* ktx */ = { + isa = PBXGroup; + children = ( + AA54A1DC26E52CE100485C4A /* lib */, + ); + path = ktx; + sourceTree = ""; + }; + AA54A1DC26E52CE100485C4A /* lib */ = { + isa = PBXGroup; + children = ( + AA54A1E126E52CE100485C4A /* checkheader.c */, + AA54A1E226E52CE100485C4A /* errstr.c */, + AA54A1E026E52CE100485C4A /* etcdec.cxx */, + AA54A1E426E52CE100485C4A /* filestream.c */, + AA54A1F526E52CE100485C4A /* filestream.h */, + AA54A1ED26E52CE100485C4A /* hashlist.c */, + AA54A1F626E52CE100485C4A /* hashtable.c */, + AA54A1EB26E52CE100485C4A /* ktxint.h */, + AA54A1E626E52CE100485C4A /* mainpage.md */, + AA54A1DD26E52CE100485C4A /* memstream.c */, + AA54A1F226E52CE100485C4A /* memstream.h */, + AA54A1EC26E52CE100485C4A /* stream.h */, + AA54A1F926E52CE100485C4A /* swap.c */, + AA54A1EA26E52CE100485C4A /* texture.c */, + AA54A1F026E52CE100485C4A /* uthash.h */, + AA54A1E926E52CE100485C4A /* vk_format.h */, + AA54A1DE26E52CE100485C4A /* vk_funclist.inl */, + AA54A1EE26E52CE100485C4A /* vk_funcs.c */, + AA54A1FB26E52CE100485C4A /* vk_funcs.h */, + AA54A1E326E52CE100485C4A /* writer.c */, + ); + path = lib; + sourceTree = ""; + }; + AA54A20026E52CE100485C4A /* imgui */ = { + isa = PBXGroup; + children = ( + AA54A20326E52CE100485C4A /* imconfig.h */, + AA54A20A26E52CE100485C4A /* imgui_demo.cpp */, + AA54A20B26E52CE100485C4A /* imgui_draw.cpp */, + AA54A20726E52CE100485C4A /* imgui_internal.h */, + AA54A20426E52CE100485C4A /* imgui_widgets.cpp */, + AA54A20626E52CE100485C4A /* imgui.cpp */, + AA54A20126E52CE100485C4A /* imgui.h */, + AA54A20826E52CE100485C4A /* imstb_rectpack.h */, + AA54A20226E52CE100485C4A /* imstb_textedit.h */, + AA54A20526E52CE100485C4A /* imstb_truetype.h */, + AA54A20926E52CE100485C4A /* LICENSE.txt */, + ); + path = imgui; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -409,6 +520,9 @@ files = ( A9B67B7F1C3AAE9800373FFD /* Icon.png in Resources */, A9B67B801C3AAE9800373FFD /* Main.storyboard in Resources */, + AA54A6C626E52CE300485C4A /* mainpage.md in Resources */, + AA54A6E226E52CE400485C4A /* LICENSE.txt in Resources */, + AA54A6BA26E52CE300485C4A /* vk_funclist.inl in Resources */, A9B67B7E1C3AAE9800373FFD /* Default~ipad.png in Resources */, A9B67B7D1C3AAE9800373FFD /* Default-568h@2x.png in Resources */, A98703D91E9D382A0066959C /* data in Resources */, @@ -419,6 +533,9 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + AA54A6E326E52CE400485C4A /* LICENSE.txt in Resources */, + AA54A6BB26E52CE300485C4A /* vk_funclist.inl in Resources */, + AA54A6C726E52CE300485C4A /* mainpage.md in Resources */, A9B67B911C3AAEA200373FFD /* macOS.xcassets in Resources */, A98703DA1E9D382A0066959C /* data in Resources */, A9B67B901C3AAEA200373FFD /* Main.storyboard in Resources */, @@ -432,15 +549,35 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + AA54A1C426E5277600485C4A /* VulkanTexture.cpp in Sources */, + AA54A6CE26E52CE400485C4A /* vk_funcs.c in Sources */, + AA54A6C426E52CE300485C4A /* filestream.c in Sources */, + AA54A6C026E52CE300485C4A /* errstr.c in Sources */, A951FF171E9C349000FA9144 /* VulkanDebug.cpp in Sources */, + AA54A6E626E52CE400485C4A /* imgui_draw.cpp in Sources */, A9BC9B1C1EE8421F00384233 /* MVKExample.cpp in Sources */, + AA54A6BC26E52CE300485C4A /* etcdec.cxx in Sources */, + AA54A6D226E52CE400485C4A /* hashtable.c in Sources */, + AA54A6B826E52CE300485C4A /* memstream.c in Sources */, + AA54A6C226E52CE300485C4A /* writer.c in Sources */, C9A79EFC204504E000696219 /* VulkanUIOverlay.cpp in Sources */, + AA54A6DE26E52CE400485C4A /* imgui_widgets.cpp in Sources */, A9B67B7A1C3AAE9800373FFD /* DemoViewController.mm in Sources */, A9B67B781C3AAE9800373FFD /* AppDelegate.m in Sources */, + AA54A6CA26E52CE300485C4A /* texture.c in Sources */, C9788FD52044D78D00AB0892 /* VulkanAndroid.cpp in Sources */, A951FF1B1E9C349000FA9144 /* VulkanTools.cpp in Sources */, + AA54A1BC26E5276000485C4A /* VulkanglTFModel.cpp in Sources */, + AA54A6CC26E52CE300485C4A /* hashlist.c in Sources */, A951FF191E9C349000FA9144 /* vulkanexamplebase.cpp in Sources */, + AA54A1B426E5274500485C4A /* VulkanBuffer.cpp in Sources */, + AA54A6D826E52CE400485C4A /* swap.c in Sources */, + AA54A6BE26E52CE300485C4A /* checkheader.c in Sources */, A9B67B7C1C3AAE9800373FFD /* main.m in Sources */, + AA54A1B826E5275300485C4A /* VulkanDevice.cpp in Sources */, + AA54A1C026E5276C00485C4A /* VulkanSwapChain.cpp in Sources */, + AA54A6E426E52CE400485C4A /* imgui_demo.cpp in Sources */, + AA54A6E026E52CE400485C4A /* imgui.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -449,23 +586,34 @@ buildActionMask = 2147483647; files = ( C9A79EFD2045051D00696219 /* VulkanUIOverlay.cpp in Sources */, + AA54A6CF26E52CE400485C4A /* vk_funcs.c in Sources */, + AA54A6C526E52CE300485C4A /* filestream.c in Sources */, + AA54A6C126E52CE300485C4A /* errstr.c in Sources */, C9A79EFE2045051D00696219 /* VulkanUIOverlay.h in Sources */, - C9A79EF12045045E00696219 /* stb_textedit.h in Sources */, - C9A79EF22045045E00696219 /* imconfig.h in Sources */, - C9A79EF32045045E00696219 /* imgui_demo.cpp in Sources */, - C9A79EF42045045E00696219 /* imgui_draw.cpp in Sources */, - C9A79EF52045045E00696219 /* imgui_internal.h in Sources */, - C9A79EF62045045E00696219 /* stb_rect_pack.h in Sources */, - C9A79EF72045045E00696219 /* imgui.h in Sources */, - C9A79EF82045045E00696219 /* stb_truetype.h in Sources */, - C9A79EF92045045E00696219 /* imgui.cpp in Sources */, + AA54A6E726E52CE400485C4A /* imgui_draw.cpp in Sources */, + AA54A1B526E5274500485C4A /* VulkanBuffer.cpp in Sources */, + AA54A6BD26E52CE300485C4A /* etcdec.cxx in Sources */, + AA54A6D326E52CE400485C4A /* hashtable.c in Sources */, + AA54A6B926E52CE300485C4A /* memstream.c in Sources */, + AA54A6C326E52CE300485C4A /* writer.c in Sources */, + AA54A1B926E5275300485C4A /* VulkanDevice.cpp in Sources */, + AA54A6DF26E52CE400485C4A /* imgui_widgets.cpp in Sources */, + AA54A1BD26E5276000485C4A /* VulkanglTFModel.cpp in Sources */, A951FF181E9C349000FA9144 /* VulkanDebug.cpp in Sources */, + AA54A6CB26E52CE300485C4A /* texture.c in Sources */, A9BC9B1D1EE8421F00384233 /* MVKExample.cpp in Sources */, A9B67B8C1C3AAEA200373FFD /* AppDelegate.m in Sources */, + AA54A1C126E5276C00485C4A /* VulkanSwapChain.cpp in Sources */, + AA54A6CD26E52CE400485C4A /* hashlist.c in Sources */, A9B67B8F1C3AAEA200373FFD /* main.m in Sources */, + AA54A1C526E5277600485C4A /* VulkanTexture.cpp in Sources */, + AA54A6D926E52CE400485C4A /* swap.c in Sources */, + AA54A6BF26E52CE300485C4A /* checkheader.c in Sources */, A951FF1C1E9C349000FA9144 /* VulkanTools.cpp in Sources */, A951FF1A1E9C349000FA9144 /* vulkanexamplebase.cpp in Sources */, A9B67B8D1C3AAEA200373FFD /* DemoViewController.mm in Sources */, + AA54A6E526E52CE400485C4A /* imgui_demo.cpp in Sources */, + AA54A6E126E52CE400485C4A /* imgui.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -477,7 +625,7 @@ buildSettings = { CODE_SIGN_IDENTITY = "iPhone Developer"; DEVELOPMENT_TEAM = VU3TCKU48B; - GCC_PREFIX_HEADER = "$(SRCROOT)/iOS/Prefix.pch"; + GCC_PREFIX_HEADER = ""; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", "DEBUG=1", @@ -488,9 +636,7 @@ INFOPLIST_FILE = "$(SRCROOT)/iOS/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "@executable_path"; - LIBRARY_SEARCH_PATHS = ( - "\"$(SRCROOT)/MoltenVK/iOS\"", - ); + LIBRARY_SEARCH_PATHS = "\"$(SRCROOT)/MoltenVK/dylib/iOS\""; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALID_ARCHS = arm64; @@ -502,7 +648,7 @@ buildSettings = { CODE_SIGN_IDENTITY = "iPhone Developer"; DEVELOPMENT_TEAM = VU3TCKU48B; - GCC_PREFIX_HEADER = "$(SRCROOT)/iOS/Prefix.pch"; + GCC_PREFIX_HEADER = ""; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", VK_USE_PLATFORM_IOS_MVK, @@ -511,9 +657,7 @@ INFOPLIST_FILE = "$(SRCROOT)/iOS/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "@executable_path"; - LIBRARY_SEARCH_PATHS = ( - "\"$(SRCROOT)/MoltenVK/iOS\"", - ); + LIBRARY_SEARCH_PATHS = "\"$(SRCROOT)/MoltenVK/dylib/iOS\""; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALID_ARCHS = arm64; @@ -526,7 +670,7 @@ ARCHS = "$(ARCHS_STANDARD)"; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COMBINE_HIDPI_IMAGES = YES; - GCC_PREFIX_HEADER = "$(SRCROOT)/macOS/Prefix.pch"; + GCC_PREFIX_HEADER = ""; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", _DEBUG, @@ -539,10 +683,7 @@ ); INFOPLIST_FILE = "$(SRCROOT)/macOS/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "@executable_path"; - LIBRARY_SEARCH_PATHS = ( - "\"$(SRCROOT)/MoltenVK/macOS\"", - "$(PROJECT_DIR)/MoltenVK/macOS", - ); + LIBRARY_SEARCH_PATHS = "\"$(SRCROOT)/MoltenVK/dylib/macOS\""; MACOSX_DEPLOYMENT_TARGET = 10.11; SDKROOT = macosx; }; @@ -554,16 +695,14 @@ ARCHS = "$(ARCHS_STANDARD)"; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COMBINE_HIDPI_IMAGES = YES; - GCC_PREFIX_HEADER = "$(SRCROOT)/macOS/Prefix.pch"; + GCC_PREFIX_HEADER = ""; GCC_PREPROCESSOR_DEFINITIONS = VK_USE_PLATFORM_MACOS_MVK; "GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = VK_USE_PLATFORM_MACOS_MVK; INFOPLIST_FILE = "$(SRCROOT)/macOS/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "@executable_path"; - LIBRARY_SEARCH_PATHS = ( - "\"$(SRCROOT)/MoltenVK/macOS\"", - "$(PROJECT_DIR)/MoltenVK/macOS", - ); + LIBRARY_SEARCH_PATHS = "\"$(SRCROOT)/MoltenVK/dylib/macOS\""; MACOSX_DEPLOYMENT_TARGET = 10.11; + ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; }; name = Release; @@ -611,6 +750,7 @@ HEADER_SEARCH_PATHS = ( "\"$(SRCROOT)/MoltenVK/include\"", "\"$(SRCROOT)/../external\"/**", + "\"$(SRCROOT)/../base\"", ); ONLY_ACTIVE_ARCH = YES; PRODUCT_BUNDLE_IDENTIFIER = "com.moltenvk.${PRODUCT_NAME:identifier}"; @@ -658,6 +798,7 @@ HEADER_SEARCH_PATHS = ( "\"$(SRCROOT)/MoltenVK/include\"", "\"$(SRCROOT)/../external\"/**", + "\"$(SRCROOT)/../base\"", ); PRODUCT_BUNDLE_IDENTIFIER = "com.moltenvk.${PRODUCT_NAME:identifier}"; PRODUCT_NAME = "${PROJECT}"; diff --git a/xcode/ios/DemoViewController.mm b/xcode/ios/DemoViewController.mm index 2629623f..a8d4ca3c 100644 --- a/xcode/ios/DemoViewController.mm +++ b/xcode/ios/DemoViewController.mm @@ -10,7 +10,7 @@ #include "MVKExample.h" -const std::string VulkanExampleBase::getAssetPath() { +const std::string getAssetPath() { return [NSBundle.mainBundle.resourcePath stringByAppendingString: @"/data/"].UTF8String; } @@ -55,7 +55,8 @@ const std::string VulkanExampleBase::getAssetPath() { -(BOOL) canBecomeFirstResponder { return _viewHasAppeared; } -(void) renderFrame { - _mvkExample->renderFrame(); + //_mvkExample->renderFrame(); + _mvkExample->nextFrame(); // SRS - Call MVKExample::nextFrame() to animate frames vs. MVKExample::renderFrame() for static image } -(void) dealloc { diff --git a/xcode/macos/DemoViewController.mm b/xcode/macos/DemoViewController.mm index 657f0b5f..f08ded77 100644 --- a/xcode/macos/DemoViewController.mm +++ b/xcode/macos/DemoViewController.mm @@ -10,8 +10,7 @@ #include "MVKExample.h" - -const std::string VulkanExampleBase::getAssetPath() { +const std::string getAssetPath() { return [NSBundle.mainBundle.resourcePath stringByAppendingString: @"/data/"].UTF8String; } @@ -22,7 +21,8 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* target) { - ((MVKExample*)target)->renderFrame(); + //((MVKExample*)target)->renderFrame(); + ((MVKExample*)target)->nextFrame(); // SRS - Call MVKExample::nextFrame() to animate frames vs. MVKExample::renderFrame() for static image return kCVReturnSuccess; } From 28d98b9ee7827976bb3ea9bb541e035fafe50b77 Mon Sep 17 00:00:00 2001 From: Stephen Saunders Date: Sat, 11 Sep 2021 11:36:27 -0400 Subject: [PATCH 03/36] Revert changes to vulkanexamplebase.h and expose displayLinkOutputCb() to DemoViewController --- base/vulkanexamplebase.h | 6 ++---- xcode/MVKExample.cpp | 4 ++-- xcode/MVKExample.h | 2 +- xcode/macos/DemoViewController.mm | 2 +- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/base/vulkanexamplebase.h b/base/vulkanexamplebase.h index 2b6eb03c..14644f6b 100644 --- a/base/vulkanexamplebase.h +++ b/base/vulkanexamplebase.h @@ -102,7 +102,7 @@ private: bool resizing = false; void windowResize(); void handleMouseMove(int32_t x, int32_t y); -// void nextFrame(); // SRS - make VulkanExampleBase::nextFrame() public + void nextFrame(); void updateOverlay(); void createPipelineCache(); void createCommandPool(); @@ -401,9 +401,7 @@ public: /** @brief Presents the current image to the swap chain */ void submitFrame(); /** @brief (Virtual) Default image acquire + submission and command buffer submission function */ - void renderFrame(); // SRS - Don't think this needs to be virtual since render() is virtual - /** @brief Draws and advances to the next frame */ - void nextFrame(); // SRS - make VulkanExampleBase::nextFrame() public + virtual void renderFrame(); /** @brief (Virtual) Called when the UI overlay is updating, can be used to add custom elements to the overlay */ virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay); diff --git a/xcode/MVKExample.cpp b/xcode/MVKExample.cpp index 5b00eacc..4ecf8f3e 100644 --- a/xcode/MVKExample.cpp +++ b/xcode/MVKExample.cpp @@ -13,8 +13,8 @@ void MVKExample::renderFrame() { _vulkanExample->renderFrame(); } -void MVKExample::nextFrame() { // SRS - expose VulkanExampleBase::nextFrame() to DemoViewController - _vulkanExample->nextFrame(); +void MVKExample::displayLinkOutputCb() { // SRS - expose VulkanExampleBase::displayLinkOutputCb() to DemoViewController + _vulkanExample->displayLinkOutputCb(); } void MVKExample::keyPressed(uint32_t keyCode) { diff --git a/xcode/MVKExample.h b/xcode/MVKExample.h index dd03e713..f926d529 100644 --- a/xcode/MVKExample.h +++ b/xcode/MVKExample.h @@ -14,7 +14,7 @@ class MVKExample { public: void renderFrame(); - void nextFrame(); // SRS - expose VulkanExampleBase::nextFrame() to DemoViewController + void displayLinkOutputCb(); // SRS - expose VulkanExampleBase::displayLinkOutputCb() to DemoViewController void keyPressed(uint32_t keyCode); MVKExample(void* view); diff --git a/xcode/macos/DemoViewController.mm b/xcode/macos/DemoViewController.mm index f08ded77..15f7dbc0 100644 --- a/xcode/macos/DemoViewController.mm +++ b/xcode/macos/DemoViewController.mm @@ -22,7 +22,7 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, CVOptionFlags* flagsOut, void* target) { //((MVKExample*)target)->renderFrame(); - ((MVKExample*)target)->nextFrame(); // SRS - Call MVKExample::nextFrame() to animate frames vs. MVKExample::renderFrame() for static image + ((MVKExample*)target)->displayLinkOutputCb(); // SRS - Call MVKExample::displayLinkOutputCb() to animate frames vs. MVKExample::renderFrame() for static image return kCVReturnSuccess; } From a74afb20fce9738b5f4b511b1d1e35e36a2bfcf4 Mon Sep 17 00:00:00 2001 From: Stephen Saunders Date: Sun, 12 Sep 2021 02:34:38 -0400 Subject: [PATCH 04/36] Handle keyboard and mouse events, adjust frameTimer scaling for macOS --- base/vulkanexamplebase.cpp | 4 ++ xcode/MVKExample.cpp | 95 ++++++++++++++++++++++++++++++- xcode/MVKExample.h | 17 +++++- xcode/examples.h | 14 ++--- xcode/macos/DemoViewController.mm | 69 ++++++++++++++++++++-- 5 files changed, 181 insertions(+), 18 deletions(-) diff --git a/base/vulkanexamplebase.cpp b/base/vulkanexamplebase.cpp index c6a23bfd..028920df 100644 --- a/base/vulkanexamplebase.cpp +++ b/base/vulkanexamplebase.cpp @@ -242,7 +242,11 @@ void VulkanExampleBase::nextFrame() frameCounter++; auto tEnd = std::chrono::high_resolution_clock::now(); auto tDiff = std::chrono::duration(tEnd - tStart).count(); +#if defined(VK_USE_PLATFORM_MACOS_MVK) + frameTimer = (float)tDiff / 100.0f; // SRS - Divide by 100 for macOS - perhaps shorter tDiff due to background rendering? +#else frameTimer = (float)tDiff / 1000.0f; +#endif camera.update(frameTimer); if (camera.moving()) { diff --git a/xcode/MVKExample.cpp b/xcode/MVKExample.cpp index 4ecf8f3e..07bf519d 100644 --- a/xcode/MVKExample.cpp +++ b/xcode/MVKExample.cpp @@ -5,20 +5,109 @@ * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) */ +#include #include "MVKExample.h" #include "examples.h" -void MVKExample::renderFrame() { +/* +void MVKExample::renderFrame() { // SRS - don't need to expose VulkanExampleBase::renderFrame() to DemoViewController _vulkanExample->renderFrame(); } +*/ void MVKExample::displayLinkOutputCb() { // SRS - expose VulkanExampleBase::displayLinkOutputCb() to DemoViewController _vulkanExample->displayLinkOutputCb(); } -void MVKExample::keyPressed(uint32_t keyCode) { - _vulkanExample->keyPressed(keyCode); +void MVKExample::windowWillResize(float x, float y) +{ + _vulkanExample->windowWillResize(x, y); +} + +void MVKExample::windowDidResize() +{ + _vulkanExample->windowDidResize(); +} + +void MVKExample::keyDown(uint32_t keyCode) { + switch (keyCode) + { + case kVK_ANSI_P: + _vulkanExample->paused = !_vulkanExample->paused; + break; + case kVK_ANSI_W: + _vulkanExample->camera.keys.up = true; + break; + case kVK_ANSI_S: + _vulkanExample->camera.keys.down = true; + break; + case kVK_ANSI_A: + _vulkanExample->camera.keys.left = true; + break; + case kVK_ANSI_D: + _vulkanExample->camera.keys.right = true; + break; + default: + break; + } +} + +void MVKExample::keyUp(uint32_t keyCode) { + switch (keyCode) + { + case kVK_ANSI_W: + _vulkanExample->camera.keys.up = false; + break; + case kVK_ANSI_S: + _vulkanExample->camera.keys.down = false; + break; + case kVK_ANSI_A: + _vulkanExample->camera.keys.left = false; + break; + case kVK_ANSI_D: + _vulkanExample->camera.keys.right = false; + break; + default: + break; + } +} + +void MVKExample::mouseDown(double x, double y) +{ + _vulkanExample->mousePos = glm::vec2(x, y); + _vulkanExample->mouseButtons.left = true; +} + +void MVKExample::mouseUp(double x, double y) +{ + _vulkanExample->mousePos = glm::vec2(x, y); + _vulkanExample->mouseButtons.left = false; +} + +void MVKExample::otherMouseDown() +{ + _vulkanExample->mouseButtons.right = true; +} + +void MVKExample::otherMouseUp() +{ + _vulkanExample->mouseButtons.right = false; +} + +void MVKExample::mouseDragged(double x, double y) +{ + _vulkanExample->mouseDragged(x, y); +} + +void MVKExample::mouseMoved(double x, double y) +{ + _vulkanExample->mouseDragged(x, y); +} + +void MVKExample::scrollWheel(short wheelDelta) +{ + _vulkanExample->camera.translate(glm::vec3(0.0f, 0.0f, wheelDelta * 0.05f * _vulkanExample->camera.movementSpeed)); } MVKExample::MVKExample(void* view) { diff --git a/xcode/MVKExample.h b/xcode/MVKExample.h index f926d529..64a4407d 100644 --- a/xcode/MVKExample.h +++ b/xcode/MVKExample.h @@ -13,9 +13,22 @@ class MVKExample { public: - void renderFrame(); + //void renderFrame(); // SRS - don't need to expose VulkanExampleBase::renderFrame() to DemoViewController void displayLinkOutputCb(); // SRS - expose VulkanExampleBase::displayLinkOutputCb() to DemoViewController - void keyPressed(uint32_t keyCode); + + void windowWillResize(float x, float y); // SRS - expose window resize events to DemoViewController + void windowDidResize(); + + void keyDown(uint32_t keyCode); // SRS - expose keyboard events to DemoViewController + void keyUp(uint32_t keyCode); + + void mouseDown(double x, double y); // SRS - expose mouse events to DemoViewController + void mouseUp(double x, double y); + void otherMouseDown(); + void otherMouseUp(); + void mouseDragged(double x, double y); + void mouseMoved(double x, double y); + void scrollWheel(short wheelDelta); MVKExample(void* view); ~MVKExample(); diff --git a/xcode/examples.h b/xcode/examples.h index 94c7f59a..975f6f87 100644 --- a/xcode/examples.h +++ b/xcode/examples.h @@ -39,7 +39,7 @@ # include "../examples/texture/texture.cpp" #endif -// Does not run. Metal does not support passing matrices between shader stages. +// Does not run. Metal does not support passing matrices between shader stages. Update: runs on macOS Big Sur with Vulksn SDK 1.2.189.0 #ifdef MVK_texturecubemap # include "../examples/texturecubemap/texturecubemap.cpp" #endif @@ -58,7 +58,7 @@ # include "../examples/dynamicuniformbuffer/dynamicuniformbuffer.cpp" #endif -// Does not run. Metal does not support passing arrays between shader stages. +// Does not run. Metal does not support passing arrays between shader stages. Update: runs on macOS Big Sur with Vulksn SDK 1.2.189.0 #ifdef MVK_pushconstants # include "../examples/pushconstants/pushconstants.cpp" #endif @@ -102,7 +102,7 @@ # include "../examples/indirectdraw/indirectdraw.cpp" #endif -// Does not run. Metal does not support passing matrices between shader stages. +// Does not run. Metal does not support passing matrices between shader stages. Update: runs on macOS Big Sur with Vulksn SDK 1.2.189.0 #ifdef MVK_hdr # include "../examples/hdr/hdr.cpp" #endif @@ -111,7 +111,7 @@ # include "../examples/occlusionquery/occlusionquery.cpp" #endif -// Does not run. Sampler arrays require Metal 2. +// Does not run. Sampler arrays require Metal 2. Update: runs on macOS Big Sur with Vulksn SDK 1.2.189.0 #ifdef MVK_texturemipmapgen # include "../examples/texturemipmapgen/texturemipmapgen.cpp" #endif @@ -128,9 +128,9 @@ # include "../examples/shadowmappingomni/shadowmappingomni.cpp" #endif -#ifdef MVK_skeletalanimation -# include "../examples/skeletalanimation/skeletalanimation.cpp" -#endif +//#ifdef MVK_skeletalanimation +//# include "../examples/skeletalanimation/skeletalanimation.cpp" +//#endif #ifdef MVK_bloom # include "../examples/bloom/bloom.cpp" diff --git a/xcode/macos/DemoViewController.mm b/xcode/macos/DemoViewController.mm index 15f7dbc0..3f1939ce 100644 --- a/xcode/macos/DemoViewController.mm +++ b/xcode/macos/DemoViewController.mm @@ -26,12 +26,12 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, return kCVReturnSuccess; } +MVKExample* _mvkExample; #pragma mark - #pragma mark DemoViewController @implementation DemoViewController { - MVKExample* _mvkExample; CVDisplayLinkRef _displayLink; } @@ -48,17 +48,24 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, CVDisplayLinkStart(_displayLink); } +// SRS - Handle window resize events +-(NSSize) windowWillResize:(NSWindow*) sender toSize:(NSSize)frameSize { + CVDisplayLinkStop(_displayLink); + _mvkExample->windowWillResize(frameSize.width, frameSize.height); + return frameSize; +} + +-(void) windowDidResize:(NSNotification*) notification { + _mvkExample->windowDidResize(); + CVDisplayLinkStart(_displayLink); +} + -(void) dealloc { CVDisplayLinkRelease(_displayLink); delete _mvkExample; [super dealloc]; } -// Handle keyboard input --(void) keyDown:(NSEvent*) theEvent { - _mvkExample->keyPressed(theEvent.keyCode); -} - @end @@ -83,4 +90,54 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, -(BOOL) acceptsFirstResponder { return YES; } +// SRS - Handle keyboard events +-(void) keyDown:(NSEvent*) theEvent { + _mvkExample->keyDown(theEvent.keyCode); +} + +-(void) keyUp:(NSEvent*) theEvent { + _mvkExample->keyUp(theEvent.keyCode); +} + +// SRS - Handle mouse events +-(NSPoint) getMouseLocalPoint:(NSEvent*) theEvent { + NSPoint location = [theEvent locationInWindow]; + NSPoint point = [self convertPoint:location fromView:nil]; + point.y = self.frame.size.height - point.y; + return point; +} + +-(void) mouseDown:(NSEvent*) theEvent { + auto point = [self getMouseLocalPoint:theEvent]; + _mvkExample->mouseDown(point.x, point.y); +} + +-(void) mouseUp:(NSEvent*) theEvent { + auto point = [self getMouseLocalPoint:theEvent]; + _mvkExample->mouseUp(point.x, point.y); +} + +-(void) otherMouseDown:(NSEvent*) theEvent { + _mvkExample->otherMouseDown(); +} + +-(void) otherMouseUp:(NSEvent*) theEvent { + _mvkExample->otherMouseUp(); +} + +-(void) mouseDragged:(NSEvent*) theEvent { + auto point = [self getMouseLocalPoint:theEvent]; + _mvkExample->mouseDragged(point.x, point.y); +} + +-(void) mouseMoved:(NSEvent*) theEvent { + auto point = [self getMouseLocalPoint:theEvent]; + _mvkExample->mouseDragged(point.x, point.y); +} + +-(void) scrollWheel:(NSEvent*) theEvent { + short wheelDelta = [theEvent deltaY]; + _mvkExample->scrollWheel(wheelDelta); +} + @end From 3941a5becdccd4adc232f7e550521b9e6644539a Mon Sep 17 00:00:00 2001 From: Stephen Saunders Date: Mon, 13 Sep 2021 01:51:30 -0400 Subject: [PATCH 05/36] Restore keyPressed() function to support MVK_textoverlay sample --- xcode/MVKExample.cpp | 31 +++++++++++++------------------ xcode/MVKExample.h | 3 ++- xcode/macos/DemoViewController.mm | 1 + 3 files changed, 16 insertions(+), 19 deletions(-) diff --git a/xcode/MVKExample.cpp b/xcode/MVKExample.cpp index 07bf519d..df8ac5e5 100644 --- a/xcode/MVKExample.cpp +++ b/xcode/MVKExample.cpp @@ -20,16 +20,18 @@ void MVKExample::displayLinkOutputCb() { // SRS - expose VulkanExampl _vulkanExample->displayLinkOutputCb(); } -void MVKExample::windowWillResize(float x, float y) -{ +void MVKExample::windowWillResize(float x, float y) { _vulkanExample->windowWillResize(x, y); } -void MVKExample::windowDidResize() -{ +void MVKExample::windowDidResize() { _vulkanExample->windowDidResize(); } +void MVKExample::keyPressed(uint32_t keyCode) { + _vulkanExample->keyPressed(keyCode); +} + void MVKExample::keyDown(uint32_t keyCode) { switch (keyCode) { @@ -73,40 +75,33 @@ void MVKExample::keyUp(uint32_t keyCode) { } } -void MVKExample::mouseDown(double x, double y) -{ +void MVKExample::mouseDown(double x, double y) { _vulkanExample->mousePos = glm::vec2(x, y); _vulkanExample->mouseButtons.left = true; } -void MVKExample::mouseUp(double x, double y) -{ +void MVKExample::mouseUp(double x, double y) { _vulkanExample->mousePos = glm::vec2(x, y); _vulkanExample->mouseButtons.left = false; } -void MVKExample::otherMouseDown() -{ +void MVKExample::otherMouseDown() { _vulkanExample->mouseButtons.right = true; } -void MVKExample::otherMouseUp() -{ +void MVKExample::otherMouseUp() { _vulkanExample->mouseButtons.right = false; } -void MVKExample::mouseDragged(double x, double y) -{ +void MVKExample::mouseDragged(double x, double y) { _vulkanExample->mouseDragged(x, y); } -void MVKExample::mouseMoved(double x, double y) -{ +void MVKExample::mouseMoved(double x, double y) { _vulkanExample->mouseDragged(x, y); } -void MVKExample::scrollWheel(short wheelDelta) -{ +void MVKExample::scrollWheel(short wheelDelta) { _vulkanExample->camera.translate(glm::vec3(0.0f, 0.0f, wheelDelta * 0.05f * _vulkanExample->camera.movementSpeed)); } diff --git a/xcode/MVKExample.h b/xcode/MVKExample.h index 64a4407d..34cb35e6 100644 --- a/xcode/MVKExample.h +++ b/xcode/MVKExample.h @@ -19,7 +19,8 @@ public: void windowWillResize(float x, float y); // SRS - expose window resize events to DemoViewController void windowDidResize(); - void keyDown(uint32_t keyCode); // SRS - expose keyboard events to DemoViewController + void keyPressed(uint32_t keyCode); // SRS - expose keyboard events to DemoViewController + void keyDown(uint32_t keyCode); void keyUp(uint32_t keyCode); void mouseDown(double x, double y); // SRS - expose mouse events to DemoViewController diff --git a/xcode/macos/DemoViewController.mm b/xcode/macos/DemoViewController.mm index 3f1939ce..a58a81d1 100644 --- a/xcode/macos/DemoViewController.mm +++ b/xcode/macos/DemoViewController.mm @@ -92,6 +92,7 @@ MVKExample* _mvkExample; // SRS - Handle keyboard events -(void) keyDown:(NSEvent*) theEvent { + _mvkExample->keyPressed(theEvent.keyCode); _mvkExample->keyDown(theEvent.keyCode); } From 57e650b653fd72ed154ee05a47e7f0cf9c38cd47 Mon Sep 17 00:00:00 2001 From: Stephen Saunders Date: Wed, 15 Sep 2021 16:19:34 -0400 Subject: [PATCH 06/36] Support right & middle mouse dragging, set macOS frameTimer based on vsync refresh period --- base/vulkanexamplebase.cpp | 4 ++-- base/vulkanexamplebase.h | 1 + xcode/MVKExample.cpp | 22 +++++++++++++++++----- xcode/MVKExample.h | 3 +++ xcode/macos/DemoViewController.mm | 27 ++++++++++++++++++++++++++- 5 files changed, 49 insertions(+), 8 deletions(-) diff --git a/base/vulkanexamplebase.cpp b/base/vulkanexamplebase.cpp index 028920df..00ef0112 100644 --- a/base/vulkanexamplebase.cpp +++ b/base/vulkanexamplebase.cpp @@ -242,8 +242,8 @@ void VulkanExampleBase::nextFrame() frameCounter++; auto tEnd = std::chrono::high_resolution_clock::now(); auto tDiff = std::chrono::duration(tEnd - tStart).count(); -#if defined(VK_USE_PLATFORM_MACOS_MVK) - frameTimer = (float)tDiff / 100.0f; // SRS - Divide by 100 for macOS - perhaps shorter tDiff due to background rendering? +#if (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK)) + frameTimer = (float)tDiff * refreshPeriod; // SRS - Multiply by the display refresh period due to fixed vsync rendering on iOS and macOS #else frameTimer = (float)tDiff / 1000.0f; #endif diff --git a/base/vulkanexamplebase.h b/base/vulkanexamplebase.h index 14644f6b..4d5befcd 100644 --- a/base/vulkanexamplebase.h +++ b/base/vulkanexamplebase.h @@ -254,6 +254,7 @@ public: int64_t lastTapTime = 0; #elif (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK)) void* view; + double refreshPeriod = 1.0/60.0; // SRS - default refreshPeriod for 60 fps display #elif defined(VK_USE_PLATFORM_DIRECTFB_EXT) bool quit = false; IDirectFB *dfb = nullptr; diff --git a/xcode/MVKExample.cpp b/xcode/MVKExample.cpp index df8ac5e5..b1dc66dd 100644 --- a/xcode/MVKExample.cpp +++ b/xcode/MVKExample.cpp @@ -11,15 +11,19 @@ #include "examples.h" /* -void MVKExample::renderFrame() { // SRS - don't need to expose VulkanExampleBase::renderFrame() to DemoViewController +void MVKExample::renderFrame() { // SRS - don't need to expose VulkanExampleBase::renderFrame() to DemoViewController _vulkanExample->renderFrame(); } */ -void MVKExample::displayLinkOutputCb() { // SRS - expose VulkanExampleBase::displayLinkOutputCb() to DemoViewController +void MVKExample::displayLinkOutputCb() { // SRS - expose VulkanExampleBase::displayLinkOutputCb() to DemoViewController _vulkanExample->displayLinkOutputCb(); } +void MVKExample::getRefreshPeriod(double refreshPeriod) { // SRS - get the actual refresh period of the display + _vulkanExample->refreshPeriod = refreshPeriod; +} + void MVKExample::windowWillResize(float x, float y) { _vulkanExample->windowWillResize(x, y); } @@ -85,14 +89,22 @@ void MVKExample::mouseUp(double x, double y) { _vulkanExample->mouseButtons.left = false; } -void MVKExample::otherMouseDown() { +void MVKExample::rightMouseDown() { _vulkanExample->mouseButtons.right = true; } -void MVKExample::otherMouseUp() { +void MVKExample::rightMouseUp() { _vulkanExample->mouseButtons.right = false; } +void MVKExample::otherMouseDown() { + _vulkanExample->mouseButtons.middle = true; +} + +void MVKExample::otherMouseUp() { + _vulkanExample->mouseButtons.middle = false; +} + void MVKExample::mouseDragged(double x, double y) { _vulkanExample->mouseDragged(x, y); } @@ -109,7 +121,7 @@ MVKExample::MVKExample(void* view) { _vulkanExample = new VulkanExample(); _vulkanExample->initVulkan(); _vulkanExample->setupWindow(view); -// _vulkanExample->initSwapchain(); // SRS - initSwapchain() is now part of VulkanExampleBase::prepare() + //_vulkanExample->initSwapchain(); // SRS - initSwapchain() is now part of VulkanExampleBase::prepare() _vulkanExample->prepare(); } diff --git a/xcode/MVKExample.h b/xcode/MVKExample.h index 34cb35e6..254f3485 100644 --- a/xcode/MVKExample.h +++ b/xcode/MVKExample.h @@ -15,6 +15,7 @@ class MVKExample { public: //void renderFrame(); // SRS - don't need to expose VulkanExampleBase::renderFrame() to DemoViewController void displayLinkOutputCb(); // SRS - expose VulkanExampleBase::displayLinkOutputCb() to DemoViewController + void getRefreshPeriod(double refreshPeriod); // SRS - get the actual refresh period of the display void windowWillResize(float x, float y); // SRS - expose window resize events to DemoViewController void windowDidResize(); @@ -25,6 +26,8 @@ public: void mouseDown(double x, double y); // SRS - expose mouse events to DemoViewController void mouseUp(double x, double y); + void rightMouseDown(); + void rightMouseUp(); void otherMouseDown(); void otherMouseUp(); void mouseDragged(double x, double y); diff --git a/xcode/macos/DemoViewController.mm b/xcode/macos/DemoViewController.mm index a58a81d1..d135854b 100644 --- a/xcode/macos/DemoViewController.mm +++ b/xcode/macos/DemoViewController.mm @@ -48,7 +48,14 @@ MVKExample* _mvkExample; CVDisplayLinkStart(_displayLink); } -// SRS - Handle window resize events +// SRS - get the actual refresh period of the display +-(void) viewWillAppear { + [super viewWillAppear]; + + _mvkExample->getRefreshPeriod(CVDisplayLinkGetActualOutputVideoRefreshPeriod(_displayLink)); +} + +// SRS - Handle window resize events (FIXME: resizeable window not yet supported at init) -(NSSize) windowWillResize:(NSWindow*) sender toSize:(NSSize)frameSize { CVDisplayLinkStop(_displayLink); _mvkExample->windowWillResize(frameSize.width, frameSize.height); @@ -118,6 +125,14 @@ MVKExample* _mvkExample; _mvkExample->mouseUp(point.x, point.y); } +-(void) rightMouseDown:(NSEvent*) theEvent { + _mvkExample->rightMouseDown(); +} + +-(void) rightMouseUp:(NSEvent*) theEvent { + _mvkExample->rightMouseUp(); +} + -(void) otherMouseDown:(NSEvent*) theEvent { _mvkExample->otherMouseDown(); } @@ -131,6 +146,16 @@ MVKExample* _mvkExample; _mvkExample->mouseDragged(point.x, point.y); } +-(void) rightMouseDragged:(NSEvent*) theEvent { + auto point = [self getMouseLocalPoint:theEvent]; + _mvkExample->mouseDragged(point.x, point.y); +} + +-(void) otherMouseDragged:(NSEvent*) theEvent { + auto point = [self getMouseLocalPoint:theEvent]; + _mvkExample->mouseDragged(point.x, point.y); +} + -(void) mouseMoved:(NSEvent*) theEvent { auto point = [self getMouseLocalPoint:theEvent]; _mvkExample->mouseDragged(point.x, point.y); From f908adac687f6016621d6e42ee5eca3c5701d402 Mon Sep 17 00:00:00 2001 From: Stephen Saunders Date: Wed, 15 Sep 2021 16:21:43 -0400 Subject: [PATCH 07/36] Add all examples (with status comments) to examples.h for macOS & iOS --- xcode/examples.h | 263 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 231 insertions(+), 32 deletions(-) diff --git a/xcode/examples.h b/xcode/examples.h index 975f6f87..59952668 100644 --- a/xcode/examples.h +++ b/xcode/examples.h @@ -31,6 +31,10 @@ // BASICS +#ifdef MVK_triangle +# include "../examples/triangle/triangle.cpp" +#endif + #ifdef MVK_pipelines # include "../examples/pipelines/pipelines.cpp" #endif @@ -39,26 +43,45 @@ # include "../examples/texture/texture.cpp" #endif -// Does not run. Metal does not support passing matrices between shader stages. Update: runs on macOS Big Sur with Vulksn SDK 1.2.189.0 +#ifdef MVK_texture3d +# include "../examples/texture3d/texture3d.cpp" +#endif + +// Does not run. Metal does not support passing matrices between shader stages. +// Update: runs on macOS Big Sur with Vulksn SDK 1.2.189.0 #ifdef MVK_texturecubemap # include "../examples/texturecubemap/texturecubemap.cpp" #endif +#ifdef MVK_texturecubemaparray +# include "../examples/texturecubemaparray/texturecubemaparray.cpp" +#endif + // Runs in Release mode. Does not run in Debug mode, as Metal validation will // assert that UBO buffer length is too short for UBO size declared in shader. +// Update: runs on macOS Big Sur with Vulksn SDK 1.2.189.0 #ifdef MVK_texturearray # include "../examples/texturearray/texturearray.cpp" #endif -//#ifdef MVK_mesh -//# include "../examples/mesh/mesh.cpp" -//#endif - #ifdef MVK_dynamicuniformbuffer # include "../examples/dynamicuniformbuffer/dynamicuniformbuffer.cpp" #endif -// Does not run. Metal does not support passing arrays between shader stages. Update: runs on macOS Big Sur with Vulksn SDK 1.2.189.0 +#ifdef MVK_inlineuniformblocks +# include "../examples/inlineuniformblocks/inlineuniformblocks.cpp" +#endif + +#ifdef MVK_inputattachments +# include "../examples/inputattachments/inputattachments.cpp" +#endif + +#ifdef MVK_negativeviewportheight +# include "../examples/negativeviewportheight/negativeviewportheight.cpp" +#endif + +// Does not run. Metal does not support passing arrays between shader stages. +// Update: runs on macOS Big Sur with Vulksn SDK 1.2.189.0 #ifdef MVK_pushconstants # include "../examples/pushconstants/pushconstants.cpp" #endif @@ -71,6 +94,28 @@ # include "../examples/offscreen/offscreen.cpp" #endif +// Runs but nothing displays +#ifdef MVK_oit +# include "../examples/oit/oit.cpp" +#endif + +// Does not run - build issue. +#ifdef MVK_renderheadless +# include "../examples/renderheadless/renderheadless.cpp" +#endif + +#ifdef MVK_screenshot +# include "../examples/screenshot/screenshot.cpp" +#endif + +#ifdef MVK_stencilbuffer +# include "../examples/stencilbuffer/stencilbuffer.cpp" +#endif + +#ifdef MVK_subpasses +# include "../examples/subpasses/subpasses.cpp" +#endif + #ifdef MVK_radialblur # include "../examples/radialblur/radialblur.cpp" #endif @@ -90,8 +135,8 @@ # include "../examples/multithreading/multithreading.cpp" #endif -#ifdef MVK_gltfscenerendering -# include "../examples/gltfscenerendering/gltfscenerendering.cpp" +#ifdef MVK_multiview +# include "../examples/multiview/multiview.cpp" #endif #ifdef MVK_instancing @@ -102,7 +147,8 @@ # include "../examples/indirectdraw/indirectdraw.cpp" #endif -// Does not run. Metal does not support passing matrices between shader stages. Update: runs on macOS Big Sur with Vulksn SDK 1.2.189.0 +// Does not run. Metal does not support passing matrices between shader stages. +// Update: runs on macOS Big Sur with Vulksn SDK 1.2.189.0 #ifdef MVK_hdr # include "../examples/hdr/hdr.cpp" #endif @@ -111,63 +157,219 @@ # include "../examples/occlusionquery/occlusionquery.cpp" #endif -// Does not run. Sampler arrays require Metal 2. Update: runs on macOS Big Sur with Vulksn SDK 1.2.189.0 +// Does not run. Sampler arrays require Metal 2. +// Update: runs on macOS Big Sur with Vulksn SDK 1.2.189.0 #ifdef MVK_texturemipmapgen # include "../examples/texturemipmapgen/texturemipmapgen.cpp" #endif +// Does not run. Sparse binding not supported. +#ifdef MVK_texturesparseresidency +# include "../examples/texturesparseresidency/texturesparseresidency.cpp" +#endif + +// Runs but multisampling may not be working. #ifdef MVK_multisampling # include "../examples/multisampling/multisampling.cpp" #endif +// Runs but multisampling may not be working. +#ifdef MVK_deferredmultisampling +# include "../examples/deferredmultisampling/deferredmultisampling.cpp" +#endif + #ifdef MVK_shadowmapping # include "../examples/shadowmapping/shadowmapping.cpp" #endif +#ifdef MVK_shadowmappingcascade +# include "../examples/shadowmappingcascade/shadowmappingcascade.cpp" +#endif + #ifdef MVK_shadowmappingomni # include "../examples/shadowmappingomni/shadowmappingomni.cpp" #endif -//#ifdef MVK_skeletalanimation -//# include "../examples/skeletalanimation/skeletalanimation.cpp" -//#endif +#ifdef MVK_gltfloading +# include "../examples/gltfloading/gltfloading.cpp" +#endif + +#ifdef MVK_gltfskinning +# include "../examples/gltfskinning/gltfskinning.cpp" +#endif + +// Runs but cannot find input file. +#ifdef MVK_gltfscenerendering +# include "../examples/gltfscenerendering/gltfscenerendering.cpp" +#endif #ifdef MVK_bloom # include "../examples/bloom/bloom.cpp" #endif -// Runs in Release mode. Debug mode Metal validation will assert +// Runs in Release mode. Debug mode Metal validation will assert. // UBO buffer length is too short for UBO size declared in shader. +// Update: runs on macOS Big Sur with Vulksn SDK 1.2.189.0 #ifdef MVK_deferred # include "../examples/deferred/deferred.cpp" #endif +// Runs in Release mode, but does not display content. +// Metal does not support the use of specialization constants to set array lengths. +// Update: runs on macOS Big Sur with Vulksn SDK 1.2.189.0 +#ifdef MVK_ssao +# include "../examples/ssao/ssao.cpp" +#endif + +#ifdef MVK_pbrbasic +# include "../examples/pbrbasic/pbrbasic.cpp" +#endif + +#ifdef MVK_pbribl +# include "../examples/pbribl/pbribl.cpp" +#endif + +#ifdef MVK_pbrtexture +# include "../examples/pbrtexture/pbrtexture.cpp" +#endif + + +// RAY TRACING - Currently unsupported by MoltenVK/Metal + +// Does not run. Missing Vulkan extensions for ray tracing +#ifdef MVK_rayquery +# include "../examples/rayquery/rayquery.cpp" +#endif + +// Does not run. Missing Vulkan extensions for ray tracing +#ifdef MVK_raytracingbasic +# include "../examples/raytracingbasic/raytracingbasic.cpp" +#endif + +// Does not run. Missing Vulkan extensions for ray tracing +#ifdef MVK_raytracingcallable +# include "../examples/raytracingcallable/raytracingcallable.cpp" +#endif + +// Does not run. Missing Vulkan extensions for ray tracing +#ifdef MVK_raytracingreflections +# include "../examples/raytracingreflections/raytracingreflections.cpp" +#endif + +// Does not run. Missing Vulkan extensions for ray tracing +#ifdef MVK_raytracingshadows +# include "../examples/raytracingshadows/raytracingshadows.cpp" +#endif + + +// COMPUTE + +#ifdef MVK_computecloth +# include "../examples/computecloth/computecloth.cpp" +#endif + +#ifdef MVK_computecullandlod +# include "../examples/computecullandlod/computecullandlod.cpp" +#endif + +// Does not run - build issue. +#ifdef MVK_computeheadless +# include "../examples/computeheadless/computeheadless.cpp" +#endif + +#ifdef MVK_computenbody +# include "../examples/computenbody/computenbody.cpp" +#endif + +#ifdef MVK_computeparticles +# include "../examples/computeparticles/computeparticles.cpp" +#endif + +#ifdef MVK_computeraytracing +# include "../examples/computeraytracing/computeraytracing.cpp" +#endif + +#ifdef MVK_computeshader +# include "../examples/computeshader/computeshader.cpp" +#endif + + +// TESSELLATION + +#ifdef MVK_displacement +# include "../examples/displacement/displacement.cpp" +#endif + +#ifdef MVK_tessellation +# include "../examples/tessellation/tessellation.cpp" +#endif + +#ifdef MVK_terraintessellation +# include "../examples/terraintessellation/terraintessellation.cpp" +#endif + + +// GEOMETRY SHADER - Unsupported by Metal + // Does not run. Metal does not support geometry shaders. #ifdef MVK_deferredshadows # include "../examples/deferredshadows/deferredshadows.cpp" #endif -// Runs in Release mode, but does not display content. -// Metal does not support the use of specialization constants to set array lengths, -#ifdef MVK_ssao -# include "../examples/ssao/ssao.cpp" +// Does not run. Metal does not support geometry shaders. +#ifdef MVK_geometryshader +# include "../examples/geometryshader/geometryshader.cpp" +#endif + +// Does not run. Metal does not support geometry shaders. +#ifdef MVK_viewportarray +# include "../examples/viewportarray/viewportarray.cpp" #endif -// COMPUTE - Currently unsupported by MoltenVK +// EXTENSIONS +// Does not run. MoltenVK does not support VK_EXT_conditional_rendering. +#ifdef MVK_conditionalrender +# include "../examples/conditionalrender/conditionalrender.cpp" +#endif -// TESSELLATION - Currently unsupported by MoltenVK +// Does not run. MoltenVK does not support VK_EXT_conservative_rasterization. +#ifdef MVK_conservativeraster +# include "../examples/conservativeraster/conservativeraster.cpp" +#endif +// Does not run. MoltenVK does not support VK_NV_shading_rate_image. +#ifdef MVK_variablerateshading +# include "../examples/variablerateshading/variablerateshading.cpp" +#endif -// GEOMETRY SHADER - Unsupported by Metal - - -// EXTENSIONS - Currently unsupported by MoltenVK +// Runs. MoltenVK supports VK_EXT_debug_marker. +#ifdef MVK_debugmarker +# include "../examples/debugmarker/debugmarker.cpp" +#endif // MISC +// Does not run. Metal/MoltenVK does not support pipeline statistics. +#ifdef MVK_pipelinestatistics +# include "../examples/pipelinestatistics/pipelinestatistics.cpp" +#endif + +// Does not run. +#ifdef MVK_descriptorindexing +# include "../examples/descriptorindexing/descriptorindexing.cpp" +#endif + +#ifdef MVK_descriptorsets +# include "../examples/descriptorsets/descriptorsets.cpp" +#endif + +#ifdef MVK_pushdescriptors +# include "../examples/pushdescriptors/pushdescriptors.cpp" +#endif + #ifdef MVK_parallaxmapping # include "../examples/parallaxmapping/parallaxmapping.cpp" #endif @@ -185,14 +387,11 @@ # include "../examples/distancefieldfonts/distancefieldfonts.cpp" #endif +// Runs but mouse interaction not working. +#ifdef MVK_imgui +# include "../examples/imgui/main.cpp" +#endif + #ifdef MVK_vulkanscene # include "../examples/vulkanscene/vulkanscene.cpp" #endif - -#ifdef MVK_gltfloading -# include "../examples/gltfloading/gltfloading.cpp" -#endif - -#ifdef MVK_gltfskinning -# include "../examples/gltfskinning/gltfskinning.cpp" -#endif From d1975e91eeab1713ce1344df66030b1408382435 Mon Sep 17 00:00:00 2001 From: Stephen Saunders Date: Thu, 16 Sep 2021 01:44:45 -0400 Subject: [PATCH 08/36] Updated examples.h with sample classification and comments --- xcode/examples.h | 165 +++++++++++------------ xcode/examples.xcodeproj/project.pbxproj | 8 ++ 2 files changed, 85 insertions(+), 88 deletions(-) diff --git a/xcode/examples.h b/xcode/examples.h index 59952668..5ae4ca77 100644 --- a/xcode/examples.h +++ b/xcode/examples.h @@ -47,8 +47,6 @@ # include "../examples/texture3d/texture3d.cpp" #endif -// Does not run. Metal does not support passing matrices between shader stages. -// Update: runs on macOS Big Sur with Vulksn SDK 1.2.189.0 #ifdef MVK_texturecubemap # include "../examples/texturecubemap/texturecubemap.cpp" #endif @@ -57,9 +55,6 @@ # include "../examples/texturecubemaparray/texturecubemaparray.cpp" #endif -// Runs in Release mode. Does not run in Debug mode, as Metal validation will -// assert that UBO buffer length is too short for UBO size declared in shader. -// Update: runs on macOS Big Sur with Vulksn SDK 1.2.189.0 #ifdef MVK_texturearray # include "../examples/texturearray/texturearray.cpp" #endif @@ -80,8 +75,6 @@ # include "../examples/negativeviewportheight/negativeviewportheight.cpp" #endif -// Does not run. Metal does not support passing arrays between shader stages. -// Update: runs on macOS Big Sur with Vulksn SDK 1.2.189.0 #ifdef MVK_pushconstants # include "../examples/pushconstants/pushconstants.cpp" #endif @@ -94,20 +87,6 @@ # include "../examples/offscreen/offscreen.cpp" #endif -// Runs but nothing displays -#ifdef MVK_oit -# include "../examples/oit/oit.cpp" -#endif - -// Does not run - build issue. -#ifdef MVK_renderheadless -# include "../examples/renderheadless/renderheadless.cpp" -#endif - -#ifdef MVK_screenshot -# include "../examples/screenshot/screenshot.cpp" -#endif - #ifdef MVK_stencilbuffer # include "../examples/stencilbuffer/stencilbuffer.cpp" #endif @@ -128,6 +107,11 @@ # include "../examples/particlefire/particlefire.cpp" #endif +// Does not run - build issue on macOS. +#ifdef MVK_renderheadless +# include "../examples/renderheadless/renderheadless.cpp" +#endif + // ADVANCED @@ -135,6 +119,11 @@ # include "../examples/multithreading/multithreading.cpp" #endif +// Runs but cannot load gltf file from asset pack. +#ifdef MVK_gltfscenerendering +# include "../examples/gltfscenerendering/gltfscenerendering.cpp" +#endif + #ifdef MVK_multiview # include "../examples/multiview/multiview.cpp" #endif @@ -147,8 +136,6 @@ # include "../examples/indirectdraw/indirectdraw.cpp" #endif -// Does not run. Metal does not support passing matrices between shader stages. -// Update: runs on macOS Big Sur with Vulksn SDK 1.2.189.0 #ifdef MVK_hdr # include "../examples/hdr/hdr.cpp" #endif @@ -157,27 +144,19 @@ # include "../examples/occlusionquery/occlusionquery.cpp" #endif -// Does not run. Sampler arrays require Metal 2. -// Update: runs on macOS Big Sur with Vulksn SDK 1.2.189.0 #ifdef MVK_texturemipmapgen # include "../examples/texturemipmapgen/texturemipmapgen.cpp" #endif -// Does not run. Sparse binding not supported. +// Does not run. Sparse binding not supported by MoltenVK/Metal. #ifdef MVK_texturesparseresidency # include "../examples/texturesparseresidency/texturesparseresidency.cpp" #endif -// Runs but multisampling may not be working. #ifdef MVK_multisampling # include "../examples/multisampling/multisampling.cpp" #endif -// Runs but multisampling may not be working. -#ifdef MVK_deferredmultisampling -# include "../examples/deferredmultisampling/deferredmultisampling.cpp" -#endif - #ifdef MVK_shadowmapping # include "../examples/shadowmapping/shadowmapping.cpp" #endif @@ -198,29 +177,54 @@ # include "../examples/gltfskinning/gltfskinning.cpp" #endif -// Runs but cannot find input file. -#ifdef MVK_gltfscenerendering -# include "../examples/gltfscenerendering/gltfscenerendering.cpp" -#endif - #ifdef MVK_bloom # include "../examples/bloom/bloom.cpp" #endif -// Runs in Release mode. Debug mode Metal validation will assert. -// UBO buffer length is too short for UBO size declared in shader. -// Update: runs on macOS Big Sur with Vulksn SDK 1.2.189.0 +// Runs but nothing displays. +#ifdef MVK_oit +# include "../examples/oit/oit.cpp" +#endif + + +// DEFERRED + #ifdef MVK_deferred # include "../examples/deferred/deferred.cpp" #endif -// Runs in Release mode, but does not display content. -// Metal does not support the use of specialization constants to set array lengths. -// Update: runs on macOS Big Sur with Vulksn SDK 1.2.189.0 +// Does not run. Metal does not support geometry shaders. +#ifdef MVK_deferredshadows +# include "../examples/deferredshadows/deferredshadows.cpp" +#endif + +#ifdef MVK_deferredmultisampling +# include "../examples/deferredmultisampling/deferredmultisampling.cpp" +#endif + #ifdef MVK_ssao # include "../examples/ssao/ssao.cpp" #endif + +// DESCRIPTORS + +#ifdef MVK_descriptorsets +# include "../examples/descriptorsets/descriptorsets.cpp" +#endif + +#ifdef MVK_pushdescriptors +# include "../examples/pushdescriptors/pushdescriptors.cpp" +#endif + +// Does not run. Shader compilation fails with MoltenVK. +#ifdef MVK_descriptorindexing +# include "../examples/descriptorindexing/descriptorindexing.cpp" +#endif + + +// PHYSICALLY BASED RENDERING + #ifdef MVK_pbrbasic # include "../examples/pbrbasic/pbrbasic.cpp" #endif @@ -264,58 +268,53 @@ // COMPUTE -#ifdef MVK_computecloth -# include "../examples/computecloth/computecloth.cpp" -#endif - -#ifdef MVK_computecullandlod -# include "../examples/computecullandlod/computecullandlod.cpp" -#endif - -// Does not run - build issue. -#ifdef MVK_computeheadless -# include "../examples/computeheadless/computeheadless.cpp" +#ifdef MVK_computeparticles +# include "../examples/computeparticles/computeparticles.cpp" #endif #ifdef MVK_computenbody # include "../examples/computenbody/computenbody.cpp" #endif -#ifdef MVK_computeparticles -# include "../examples/computeparticles/computeparticles.cpp" -#endif - #ifdef MVK_computeraytracing # include "../examples/computeraytracing/computeraytracing.cpp" #endif +#ifdef MVK_computecullandlod +# include "../examples/computecullandlod/computecullandlod.cpp" +#endif + #ifdef MVK_computeshader # include "../examples/computeshader/computeshader.cpp" #endif +#ifdef MVK_computecloth +# include "../examples/computecloth/computecloth.cpp" +#endif + +// Does not run - build issue on macOS. +#ifdef MVK_computeheadless +# include "../examples/computeheadless/computeheadless.cpp" +#endif + // TESSELLATION -#ifdef MVK_displacement -# include "../examples/displacement/displacement.cpp" +#ifdef MVK_terraintessellation +# include "../examples/terraintessellation/terraintessellation.cpp" #endif #ifdef MVK_tessellation # include "../examples/tessellation/tessellation.cpp" #endif -#ifdef MVK_terraintessellation -# include "../examples/terraintessellation/terraintessellation.cpp" +#ifdef MVK_displacement +# include "../examples/displacement/displacement.cpp" #endif // GEOMETRY SHADER - Unsupported by Metal -// Does not run. Metal does not support geometry shaders. -#ifdef MVK_deferredshadows -# include "../examples/deferredshadows/deferredshadows.cpp" -#endif - // Does not run. Metal does not support geometry shaders. #ifdef MVK_geometryshader # include "../examples/geometryshader/geometryshader.cpp" @@ -329,22 +328,22 @@ // EXTENSIONS -// Does not run. MoltenVK does not support VK_EXT_conditional_rendering. +// Does not run. Requires VK_EXT_conditional_rendering. #ifdef MVK_conditionalrender # include "../examples/conditionalrender/conditionalrender.cpp" #endif -// Does not run. MoltenVK does not support VK_EXT_conservative_rasterization. +// Does not run. Requires VK_EXT_conservative_rasterization. #ifdef MVK_conservativeraster # include "../examples/conservativeraster/conservativeraster.cpp" #endif -// Does not run. MoltenVK does not support VK_NV_shading_rate_image. +// Does not run. Requires VK_NV_shading_rate_image. #ifdef MVK_variablerateshading # include "../examples/variablerateshading/variablerateshading.cpp" #endif -// Runs. MoltenVK supports VK_EXT_debug_marker. +// Runs. Requires VK_EXT_debug_marker. #ifdef MVK_debugmarker # include "../examples/debugmarker/debugmarker.cpp" #endif @@ -352,22 +351,8 @@ // MISC -// Does not run. Metal/MoltenVK does not support pipeline statistics. -#ifdef MVK_pipelinestatistics -# include "../examples/pipelinestatistics/pipelinestatistics.cpp" -#endif - -// Does not run. -#ifdef MVK_descriptorindexing -# include "../examples/descriptorindexing/descriptorindexing.cpp" -#endif - -#ifdef MVK_descriptorsets -# include "../examples/descriptorsets/descriptorsets.cpp" -#endif - -#ifdef MVK_pushdescriptors -# include "../examples/pushdescriptors/pushdescriptors.cpp" +#ifdef MVK_screenshot +# include "../examples/screenshot/screenshot.cpp" #endif #ifdef MVK_parallaxmapping @@ -387,7 +372,11 @@ # include "../examples/distancefieldfonts/distancefieldfonts.cpp" #endif -// Runs but mouse interaction not working. +// Does not run. MoltenVK/Metal does not support pipeline statistics. +#ifdef MVK_pipelinestatistics +# include "../examples/pipelinestatistics/pipelinestatistics.cpp" +#endif + #ifdef MVK_imgui # include "../examples/imgui/main.cpp" #endif diff --git a/xcode/examples.xcodeproj/project.pbxproj b/xcode/examples.xcodeproj/project.pbxproj index d4091e0d..501c306e 100644 --- a/xcode/examples.xcodeproj/project.pbxproj +++ b/xcode/examples.xcodeproj/project.pbxproj @@ -80,6 +80,8 @@ AA54A6E526E52CE400485C4A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA54A20A26E52CE100485C4A /* imgui_demo.cpp */; }; AA54A6E626E52CE400485C4A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA54A20B26E52CE100485C4A /* imgui_draw.cpp */; }; AA54A6E726E52CE400485C4A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA54A20B26E52CE100485C4A /* imgui_draw.cpp */; }; + AAB0D0BF26F24001005DC611 /* VulkanRaytracingSample.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AAB0D0BE26F24001005DC611 /* VulkanRaytracingSample.cpp */; }; + AAB0D0C026F24001005DC611 /* VulkanRaytracingSample.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AAB0D0BE26F24001005DC611 /* VulkanRaytracingSample.cpp */; }; C9788FD52044D78D00AB0892 /* VulkanAndroid.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C9788FD32044D78D00AB0892 /* VulkanAndroid.cpp */; }; C9A79EFC204504E000696219 /* VulkanUIOverlay.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C9A79EFB204504E000696219 /* VulkanUIOverlay.cpp */; }; C9A79EFD2045051D00696219 /* VulkanUIOverlay.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C9A79EFB204504E000696219 /* VulkanUIOverlay.cpp */; }; @@ -201,6 +203,8 @@ AA54A20926E52CE100485C4A /* LICENSE.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE.txt; sourceTree = ""; }; AA54A20A26E52CE100485C4A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_demo.cpp; sourceTree = ""; }; AA54A20B26E52CE100485C4A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_draw.cpp; sourceTree = ""; }; + AAB0D0BE26F24001005DC611 /* VulkanRaytracingSample.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VulkanRaytracingSample.cpp; sourceTree = ""; }; + AAB0D0C126F2400E005DC611 /* VulkanRaytracingSample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VulkanRaytracingSample.h; sourceTree = ""; }; C9788FD02044D78D00AB0892 /* benchmark.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = benchmark.hpp; sourceTree = ""; }; C9788FD22044D78D00AB0892 /* VulkanAndroid.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VulkanAndroid.h; sourceTree = ""; }; C9788FD32044D78D00AB0892 /* VulkanAndroid.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VulkanAndroid.cpp; sourceTree = ""; }; @@ -292,6 +296,8 @@ A951FF0E1E9C349000FA9144 /* VulkanInitializers.hpp */, AA54A1BA26E5276000485C4A /* VulkanglTFModel.cpp */, AA54A1BB26E5276000485C4A /* VulkanglTFModel.h */, + AAB0D0BE26F24001005DC611 /* VulkanRaytracingSample.cpp */, + AAB0D0C126F2400E005DC611 /* VulkanRaytracingSample.h */, AA54A1BF26E5276C00485C4A /* VulkanSwapChain.cpp */, AA54A1BE26E5276C00485C4A /* VulkanSwapChain.h */, AA54A1C326E5277600485C4A /* VulkanTexture.cpp */, @@ -565,6 +571,7 @@ A9B67B7A1C3AAE9800373FFD /* DemoViewController.mm in Sources */, A9B67B781C3AAE9800373FFD /* AppDelegate.m in Sources */, AA54A6CA26E52CE300485C4A /* texture.c in Sources */, + AAB0D0BF26F24001005DC611 /* VulkanRaytracingSample.cpp in Sources */, C9788FD52044D78D00AB0892 /* VulkanAndroid.cpp in Sources */, A951FF1B1E9C349000FA9144 /* VulkanTools.cpp in Sources */, AA54A1BC26E5276000485C4A /* VulkanglTFModel.cpp in Sources */, @@ -601,6 +608,7 @@ AA54A1BD26E5276000485C4A /* VulkanglTFModel.cpp in Sources */, A951FF181E9C349000FA9144 /* VulkanDebug.cpp in Sources */, AA54A6CB26E52CE300485C4A /* texture.c in Sources */, + AAB0D0C026F24001005DC611 /* VulkanRaytracingSample.cpp in Sources */, A9BC9B1D1EE8421F00384233 /* MVKExample.cpp in Sources */, A9B67B8C1C3AAEA200373FFD /* AppDelegate.m in Sources */, AA54A1C126E5276C00485C4A /* VulkanSwapChain.cpp in Sources */, From b1f10d7393ce64e8c8d2686723b60121ffd2a754 Mon Sep 17 00:00:00 2001 From: Stephen Saunders Date: Wed, 4 May 2022 00:43:14 -0400 Subject: [PATCH 09/36] Fix CMakeLists.txt for vulkanExamples.xcodeproj build, fix macOS storyboard for resizable window, set animation rate based on display refresh period --- CMakeLists.txt | 8 +++--- base/vulkanexamplebase.cpp | 35 ++++++++++++++++++++++++--- examples/CMakeLists.txt | 12 +++++++++ xcode/MVKExample.cpp | 20 +++------------ xcode/MVKExample.h | 9 +++---- xcode/macos/DemoViewController.mm | 23 +++++++----------- xcode/macos/Resources/Main.storyboard | 11 +++++---- 7 files changed, 71 insertions(+), 47 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b71d1aed..90a05c8b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -130,11 +130,11 @@ endif() IF(MSVC) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc") ELSEIF(APPLE) - if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fobjc-arc -ObjC++") - ELSE() + #if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + # SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fobjc-arc -ObjC++") + #ELSE() SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fobjc-arc -xobjective-c++") - ENDIF() + #ENDIF() ENDIF(MSVC) IF(WIN32) diff --git a/base/vulkanexamplebase.cpp b/base/vulkanexamplebase.cpp index 00ef0112..b6b3e738 100644 --- a/base/vulkanexamplebase.cpp +++ b/base/vulkanexamplebase.cpp @@ -243,7 +243,7 @@ void VulkanExampleBase::nextFrame() auto tEnd = std::chrono::high_resolution_clock::now(); auto tDiff = std::chrono::duration(tEnd - tStart).count(); #if (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK)) - frameTimer = (float)tDiff * refreshPeriod; // SRS - Multiply by the display refresh period due to fixed vsync rendering on iOS and macOS + frameTimer = (float)tDiff * refreshPeriod; // SRS - Multiply by refresh period due to displayLink callback rendering on iOS and macOS #else frameTimer = (float)tDiff / 1000.0f; #endif @@ -1515,6 +1515,10 @@ void VulkanExampleBase::handleAppCommand(android_app * app, int32_t cmd) @end +const std::string getAssetPath() { + return [NSBundle.mainBundle.resourcePath stringByAppendingString: @"/../../data/"].UTF8String; +} + static CVReturn displayLinkOutputCallback(CVDisplayLinkRef displayLink, const CVTimeStamp *inNow, const CVTimeStamp *inOutputTime, CVOptionFlags flagsIn, CVOptionFlags *flagsOut, void *displayLinkContext) @@ -1556,6 +1560,9 @@ static CVReturn displayLinkOutputCallback(CVDisplayLinkRef displayLink, const CV CVDisplayLinkCreateWithActiveCGDisplays(&displayLink); CVDisplayLinkSetOutputCallback(displayLink, &displayLinkOutputCallback, vulkanExample); CVDisplayLinkStart(displayLink); + // SRS - Pause 1 ms for displayLink startup then get the actual refresh period of the display + usleep(1000); + vulkanExample->refreshPeriod = CVDisplayLinkGetActualOutputVideoRefreshPeriod(displayLink); } - (BOOL)acceptsFirstResponder @@ -1633,22 +1640,44 @@ static CVReturn displayLinkOutputCallback(CVDisplayLinkRef displayLink, const CV vulkanExample->mouseButtons.left = false; } -- (void)otherMouseDown:(NSEvent *)event +- (void)rightMouseDown:(NSEvent *)event { vulkanExample->mouseButtons.right = true; } -- (void)otherMouseUp:(NSEvent *)event +- (void)rightMouseUp:(NSEvent *)event { vulkanExample->mouseButtons.right = false; } +- (void)otherMouseDown:(NSEvent *)event +{ + vulkanExample->mouseButtons.middle = true; +} + +- (void)otherMouseUp:(NSEvent *)event +{ + vulkanExample->mouseButtons.middle = false; +} + - (void)mouseDragged:(NSEvent *)event { auto point = [self getMouseLocalPoint:event]; vulkanExample->mouseDragged(point.x, point.y); } +- (void)rightMouseDragged:(NSEvent *)event +{ + auto point = [self getMouseLocalPoint:event]; + vulkanExample->mouseDragged(point.x, point.y); +} + +- (void)otherMouseDragged:(NSEvent *)event +{ + auto point = [self getMouseLocalPoint:event]; + vulkanExample->mouseDragged(point.x, point.y); +} + - (void)mouseMoved:(NSEvent *)event { auto point = [self getMouseLocalPoint:event]; diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 45a0b43f..a40dccfb 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -11,6 +11,18 @@ function(buildExample EXAMPLE_NAME) if(EXISTS ${EXAMPLE_FOLDER}/${EXAMPLE_NAME}.h) SET(MAIN_HEADER ${EXAMPLE_FOLDER}/${EXAMPLE_NAME}.h) ENDIF() + if(APPLE) + if(CMAKE_C_COMPILER_ID MATCHES "Clang\$") + set(OpenMP_C_FLAGS "-Xpreprocessor -fopenmp") + set(OpenMP_C_LIB_NAMES "omp") + set(OpenMP_omp_LIBRARY /opt/local/lib/libomp/libomp.dylib) + endif() + if(CMAKE_CXX_COMPILER_ID MATCHES "Clang\$") + set(OpenMP_CXX_FLAGS "-Xpreprocessor -fopenmp") + set(OpenMP_CXX_LIB_NAMES "omp") + set(OpenMP_omp_LIBRARY /opt/local/lib/libomp/libomp.dylib) + endif() + endif() find_package(OpenMP) # imgui example requires additional source files IF(${EXAMPLE_NAME} STREQUAL "imgui") diff --git a/xcode/MVKExample.cpp b/xcode/MVKExample.cpp index b1dc66dd..9ed6e36b 100644 --- a/xcode/MVKExample.cpp +++ b/xcode/MVKExample.cpp @@ -10,28 +10,14 @@ #include "MVKExample.h" #include "examples.h" -/* -void MVKExample::renderFrame() { // SRS - don't need to expose VulkanExampleBase::renderFrame() to DemoViewController - _vulkanExample->renderFrame(); -} -*/ - void MVKExample::displayLinkOutputCb() { // SRS - expose VulkanExampleBase::displayLinkOutputCb() to DemoViewController _vulkanExample->displayLinkOutputCb(); } -void MVKExample::getRefreshPeriod(double refreshPeriod) { // SRS - get the actual refresh period of the display +void MVKExample::setRefreshPeriod(double refreshPeriod) { // SRS - set VulkanExampleBase::refreshPeriod from DemoViewController displayLink _vulkanExample->refreshPeriod = refreshPeriod; } -void MVKExample::windowWillResize(float x, float y) { - _vulkanExample->windowWillResize(x, y); -} - -void MVKExample::windowDidResize() { - _vulkanExample->windowDidResize(); -} - void MVKExample::keyPressed(uint32_t keyCode) { _vulkanExample->keyPressed(keyCode); } @@ -119,10 +105,12 @@ void MVKExample::scrollWheel(short wheelDelta) { MVKExample::MVKExample(void* view) { _vulkanExample = new VulkanExample(); + width = _vulkanExample->width; // SRS - Get desired window size from VulkanExampleBase instance + height = _vulkanExample->height; _vulkanExample->initVulkan(); _vulkanExample->setupWindow(view); - //_vulkanExample->initSwapchain(); // SRS - initSwapchain() is now part of VulkanExampleBase::prepare() _vulkanExample->prepare(); + _vulkanExample->renderLoop(); // SRS - Init destWidth & destHeight, then fall through and return } MVKExample::~MVKExample() { diff --git a/xcode/MVKExample.h b/xcode/MVKExample.h index 254f3485..8e5acf47 100644 --- a/xcode/MVKExample.h +++ b/xcode/MVKExample.h @@ -13,12 +13,11 @@ class MVKExample { public: - //void renderFrame(); // SRS - don't need to expose VulkanExampleBase::renderFrame() to DemoViewController + uint32_t width; // SRS - expose VulkanExampleBase initial window size to DemoViewController + uint32_t height; + void displayLinkOutputCb(); // SRS - expose VulkanExampleBase::displayLinkOutputCb() to DemoViewController - void getRefreshPeriod(double refreshPeriod); // SRS - get the actual refresh period of the display - - void windowWillResize(float x, float y); // SRS - expose window resize events to DemoViewController - void windowDidResize(); + void setRefreshPeriod(double refreshPeriod); // SRS - set VulkanExampleBase::refreshPeriod from DemoViewController displayLink void keyPressed(uint32_t keyCode); // SRS - expose keyboard events to DemoViewController void keyDown(uint32_t keyCode); diff --git a/xcode/macos/DemoViewController.mm b/xcode/macos/DemoViewController.mm index d135854b..c1e3cf1d 100644 --- a/xcode/macos/DemoViewController.mm +++ b/xcode/macos/DemoViewController.mm @@ -22,7 +22,7 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, CVOptionFlags* flagsOut, void* target) { //((MVKExample*)target)->renderFrame(); - ((MVKExample*)target)->displayLinkOutputCb(); // SRS - Call MVKExample::displayLinkOutputCb() to animate frames vs. MVKExample::renderFrame() for static image + ((MVKExample*)target)->displayLinkOutputCb(); // SRS - Call displayLinkOutputCb() to animate frames vs. renderFrame() for static image return kCVReturnSuccess; } @@ -48,23 +48,18 @@ MVKExample* _mvkExample; CVDisplayLinkStart(_displayLink); } -// SRS - get the actual refresh period of the display +// SRS - Set window's initial content size and set VulkanExampleBase::refreshPeriod from the displayLink -(void) viewWillAppear { [super viewWillAppear]; - - _mvkExample->getRefreshPeriod(CVDisplayLinkGetActualOutputVideoRefreshPeriod(_displayLink)); -} -// SRS - Handle window resize events (FIXME: resizeable window not yet supported at init) --(NSSize) windowWillResize:(NSWindow*) sender toSize:(NSSize)frameSize { - CVDisplayLinkStop(_displayLink); - _mvkExample->windowWillResize(frameSize.width, frameSize.height); - return frameSize; -} + NSWindow* window = self.view.window; + NSSize viewSize; + viewSize.width = _mvkExample->width; + viewSize.height = _mvkExample->height; + [window setContentSize:viewSize]; + [window center]; --(void) windowDidResize:(NSNotification*) notification { - _mvkExample->windowDidResize(); - CVDisplayLinkStart(_displayLink); + _mvkExample->setRefreshPeriod(CVDisplayLinkGetActualOutputVideoRefreshPeriod(_displayLink)); } -(void) dealloc { diff --git a/xcode/macos/Resources/Main.storyboard b/xcode/macos/Resources/Main.storyboard index 52913366..e682969c 100644 --- a/xcode/macos/Resources/Main.storyboard +++ b/xcode/macos/Resources/Main.storyboard @@ -1,8 +1,8 @@ - + - + @@ -101,12 +101,13 @@ - + - - + + + From 2810087752999bb33ddd1b6567b5584f5872e2f6 Mon Sep 17 00:00:00 2001 From: Stephen Saunders Date: Mon, 9 May 2022 14:09:47 -0400 Subject: [PATCH 10/36] Fix glTF build & settings issues for macOS, fix triangle example resizing, update macOS examples.h file (cherry picked from commit 47061ff99446d8826ebe7fe187467ba638236a70) --- examples/gltfloading/gltfloading.cpp | 2 +- .../gltfscenerendering/gltfscenerendering.h | 4 +- examples/gltfskinning/gltfskinning.h | 2 +- examples/triangle/triangle.cpp | 5 ++- examples/vertexattributes/vertexattributes.h | 4 +- xcode/examples.h | 39 ++++++++++++++----- xcode/examples.xcodeproj/project.pbxproj | 4 -- 7 files changed, 39 insertions(+), 21 deletions(-) diff --git a/examples/gltfloading/gltfloading.cpp b/examples/gltfloading/gltfloading.cpp index b71a3edf..c2144ded 100644 --- a/examples/gltfloading/gltfloading.cpp +++ b/examples/gltfloading/gltfloading.cpp @@ -17,7 +17,7 @@ * If you are looking for a complete glTF implementation, check out https://github.com/SaschaWillems/Vulkan-glTF-PBR/ */ -//#define TINYGLTF_IMPLEMENTATION // SRS - Already defined in VulkanglTFModel.cpp +#define TINYGLTF_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION #define TINYGLTF_NO_STB_IMAGE_WRITE #ifdef VK_USE_PLATFORM_ANDROID_KHR diff --git a/examples/gltfscenerendering/gltfscenerendering.h b/examples/gltfscenerendering/gltfscenerendering.h index 357463fc..e02abfe6 100644 --- a/examples/gltfscenerendering/gltfscenerendering.h +++ b/examples/gltfscenerendering/gltfscenerendering.h @@ -12,10 +12,10 @@ * This sample comes with a tutorial, see the README.md in this folder */ -//#define TINYGLTF_IMPLEMENTATION // SRS - Already defined in VulkanglTFModel.cpp +#define TINYGLTF_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION #define TINYGLTF_NO_STB_IMAGE_WRITE -#define TINYGLTF_NO_STB_IMAGE +//#define TINYGLTF_NO_STB_IMAGE // SRS - Comment out to enable default image loader, otherwise LoadImageData() is undefined #define TINYGLTF_NO_EXTERNAL_IMAGE #ifdef VK_USE_PLATFORM_ANDROID_KHR #define TINYGLTF_ANDROID_LOAD_FROM_ASSETS diff --git a/examples/gltfskinning/gltfskinning.h b/examples/gltfskinning/gltfskinning.h index e60317fc..9423c01c 100644 --- a/examples/gltfskinning/gltfskinning.h +++ b/examples/gltfskinning/gltfskinning.h @@ -27,7 +27,7 @@ #include #include -//#define TINYGLTF_IMPLEMENTATION // SRS - Already defined in VulkanglTFModel.cpp +#define TINYGLTF_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION #define TINYGLTF_NO_STB_IMAGE_WRITE #ifdef VK_USE_PLATFORM_ANDROID_KHR diff --git a/examples/triangle/triangle.cpp b/examples/triangle/triangle.cpp index 77e4df8f..4a6336f7 100644 --- a/examples/triangle/triangle.cpp +++ b/examples/triangle/triangle.cpp @@ -335,7 +335,10 @@ public: void draw() { // Get next image in the swap chain (back/front buffer) - VK_CHECK_RESULT(swapChain.acquireNextImage(presentCompleteSemaphore, ¤tBuffer)); + VkResult acquire = swapChain.acquireNextImage(presentCompleteSemaphore, ¤tBuffer); + if (!((acquire == VK_SUCCESS) || (acquire == VK_SUBOPTIMAL_KHR))) { + VK_CHECK_RESULT(acquire); + } // Use a fence to wait until the command buffer has finished execution before using it again VK_CHECK_RESULT(vkWaitForFences(device, 1, &waitFences[currentBuffer], VK_TRUE, UINT64_MAX)); diff --git a/examples/vertexattributes/vertexattributes.h b/examples/vertexattributes/vertexattributes.h index af480ab0..97abf1b3 100644 --- a/examples/vertexattributes/vertexattributes.h +++ b/examples/vertexattributes/vertexattributes.h @@ -9,7 +9,7 @@ #define TINYGLTF_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION #define TINYGLTF_NO_STB_IMAGE_WRITE -#define TINYGLTF_NO_STB_IMAGE +//#define TINYGLTF_NO_STB_IMAGE // SRS - Comment out to enable default image loader, otherwise LoadImageData() is undefined #define TINYGLTF_NO_EXTERNAL_IMAGE #ifdef VK_USE_PLATFORM_ANDROID_KHR #define TINYGLTF_ANDROID_LOAD_FROM_ASSETS @@ -140,4 +140,4 @@ public: void drawSceneNode(VkCommandBuffer commandBuffer, Node node); virtual void render(); virtual void OnUpdateUIOverlay(vks::UIOverlay* overlay); -}; \ No newline at end of file +}; diff --git a/xcode/examples.h b/xcode/examples.h index 5ae4ca77..68182c49 100644 --- a/xcode/examples.h +++ b/xcode/examples.h @@ -27,7 +27,13 @@ // In the list below, the comments indicate entries that, // under certain conditions, that may not run as expected. -#define MVK_gltfskinning +#define MVK_vulkanscene + +// COMMON - Include VulkanglTFModel.cpp in all examples other than ones that already include/customize tiny_gltf.h directly +#if !defined(MVK_gltfloading) && !defined(MVK_gltfskinning) && !defined(MVK_gltfscenerendering) && !defined(MVK_vertexattributes) +#include "../base/VulkanglTFModel.cpp" +#endif + // BASICS @@ -107,7 +113,7 @@ # include "../examples/particlefire/particlefire.cpp" #endif -// Does not run - build issue on macOS. +// Build issue when using this xcode examples project, builds/runs fine using vulkanExamples project. #ifdef MVK_renderheadless # include "../examples/renderheadless/renderheadless.cpp" #endif @@ -119,7 +125,6 @@ # include "../examples/multithreading/multithreading.cpp" #endif -// Runs but cannot load gltf file from asset pack. #ifdef MVK_gltfscenerendering # include "../examples/gltfscenerendering/gltfscenerendering.cpp" #endif @@ -181,7 +186,11 @@ # include "../examples/bloom/bloom.cpp" #endif -// Runs but nothing displays. +#ifdef MVK_vertexattributes +# include "../examples/vertexattributes/vertexattributes.cpp" +#endif + +// Runs but nothing displays. MoltenVK format VK_FORMAT_R32_UINT doesn't contain VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT #ifdef MVK_oit # include "../examples/oit/oit.cpp" #endif @@ -193,11 +202,6 @@ # include "../examples/deferred/deferred.cpp" #endif -// Does not run. Metal does not support geometry shaders. -#ifdef MVK_deferredshadows -# include "../examples/deferredshadows/deferredshadows.cpp" -#endif - #ifdef MVK_deferredmultisampling # include "../examples/deferredmultisampling/deferredmultisampling.cpp" #endif @@ -292,7 +296,7 @@ # include "../examples/computecloth/computecloth.cpp" #endif -// Does not run - build issue on macOS. +// Build issue when using this xcode examples project, builds/runs fine using vulkanExamples project. #ifdef MVK_computeheadless # include "../examples/computeheadless/computeheadless.cpp" #endif @@ -320,6 +324,11 @@ # include "../examples/geometryshader/geometryshader.cpp" #endif +// Does not run. Metal does not support geometry shaders. +#ifdef MVK_deferredshadows +# include "../examples/deferredshadows/deferredshadows.cpp" +#endif + // Does not run. Metal does not support geometry shaders. #ifdef MVK_viewportarray # include "../examples/viewportarray/viewportarray.cpp" @@ -343,6 +352,16 @@ # include "../examples/variablerateshading/variablerateshading.cpp" #endif +// Does not run. Requires VK_KHR_pipeline_library and VK_EXT_graphics_pipeline_library. +#ifdef MVK_graphicspipelinelibrary +# include "../examples/graphicspipelinelibrary/graphicspipelinelibrary.cpp" +#endif + +// Does not run yet. Requires VK_KHR_dynamic_rendering (under development in MoltenVK) +#ifdef MVK_dynamicrendering +# include "../examples/dynamicrendering/dynamicrendering.cpp" +#endif + // Runs. Requires VK_EXT_debug_marker. #ifdef MVK_debugmarker # include "../examples/debugmarker/debugmarker.cpp" diff --git a/xcode/examples.xcodeproj/project.pbxproj b/xcode/examples.xcodeproj/project.pbxproj index 501c306e..173ea0da 100644 --- a/xcode/examples.xcodeproj/project.pbxproj +++ b/xcode/examples.xcodeproj/project.pbxproj @@ -38,8 +38,6 @@ AA54A1B526E5274500485C4A /* VulkanBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA54A1B226E5274500485C4A /* VulkanBuffer.cpp */; }; AA54A1B826E5275300485C4A /* VulkanDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA54A1B626E5275300485C4A /* VulkanDevice.cpp */; }; AA54A1B926E5275300485C4A /* VulkanDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA54A1B626E5275300485C4A /* VulkanDevice.cpp */; }; - AA54A1BC26E5276000485C4A /* VulkanglTFModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA54A1BA26E5276000485C4A /* VulkanglTFModel.cpp */; }; - AA54A1BD26E5276000485C4A /* VulkanglTFModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA54A1BA26E5276000485C4A /* VulkanglTFModel.cpp */; }; AA54A1C026E5276C00485C4A /* VulkanSwapChain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA54A1BF26E5276C00485C4A /* VulkanSwapChain.cpp */; }; AA54A1C126E5276C00485C4A /* VulkanSwapChain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA54A1BF26E5276C00485C4A /* VulkanSwapChain.cpp */; }; AA54A1C426E5277600485C4A /* VulkanTexture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA54A1C326E5277600485C4A /* VulkanTexture.cpp */; }; @@ -574,7 +572,6 @@ AAB0D0BF26F24001005DC611 /* VulkanRaytracingSample.cpp in Sources */, C9788FD52044D78D00AB0892 /* VulkanAndroid.cpp in Sources */, A951FF1B1E9C349000FA9144 /* VulkanTools.cpp in Sources */, - AA54A1BC26E5276000485C4A /* VulkanglTFModel.cpp in Sources */, AA54A6CC26E52CE300485C4A /* hashlist.c in Sources */, A951FF191E9C349000FA9144 /* vulkanexamplebase.cpp in Sources */, AA54A1B426E5274500485C4A /* VulkanBuffer.cpp in Sources */, @@ -605,7 +602,6 @@ AA54A6C326E52CE300485C4A /* writer.c in Sources */, AA54A1B926E5275300485C4A /* VulkanDevice.cpp in Sources */, AA54A6DF26E52CE400485C4A /* imgui_widgets.cpp in Sources */, - AA54A1BD26E5276000485C4A /* VulkanglTFModel.cpp in Sources */, A951FF181E9C349000FA9144 /* VulkanDebug.cpp in Sources */, AA54A6CB26E52CE300485C4A /* texture.c in Sources */, AAB0D0C026F24001005DC611 /* VulkanRaytracingSample.cpp in Sources */, From ae8ad09f6e5c7f00e026f5bf8df947f3a69245da Mon Sep 17 00:00:00 2001 From: Stephen Saunders Date: Mon, 9 May 2022 14:16:16 -0400 Subject: [PATCH 11/36] Fix VK_KHR_portability_subset validation errors on macOS, fix OpenMP build issues on macOS (cherry picked from commit d2f6713c418ea5bdd2c3fcee922def5854e534d4) --- base/VulkanDevice.cpp | 12 ++++++++++++ base/vulkanexamplebase.cpp | 24 ++++++++++++++++++++++++ examples/CMakeLists.txt | 23 ++++++++++++++++------- 3 files changed, 52 insertions(+), 7 deletions(-) diff --git a/base/VulkanDevice.cpp b/base/VulkanDevice.cpp index 8f1d99b9..6835a3dd 100644 --- a/base/VulkanDevice.cpp +++ b/base/VulkanDevice.cpp @@ -8,6 +8,10 @@ * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) */ +#if (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK)) +// SRS - This is needed to make visible VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME +#define VK_ENABLE_BETA_EXTENSIONS +#endif #include #include @@ -279,6 +283,14 @@ namespace vks enableDebugMarkers = true; } +#if (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK)) + // SRS - When running on iOS/macOS with MoltenVK, must enable the VK_KHR_portability_subset device extension + if (extensionSupported(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME)) + { + deviceExtensions.push_back(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME); + } +#endif + if (deviceExtensions.size() > 0) { for (const char* enabledExtension : deviceExtensions) diff --git a/base/vulkanexamplebase.cpp b/base/vulkanexamplebase.cpp index b6b3e738..2e00aa14 100644 --- a/base/vulkanexamplebase.cpp +++ b/base/vulkanexamplebase.cpp @@ -54,6 +54,14 @@ VkResult VulkanExampleBase::createInstance(bool enableValidation) #elif defined(VK_USE_PLATFORM_HEADLESS_EXT) instanceExtensions.push_back(VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME); #endif + +#if (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK)) + // SRS - When running on iOS/macOS with MoltenVK, enable VkPhysicalDeviceFeatures2 if not already enabled (required by VK_KHR_portability_subset) + if (std::find(enabledInstanceExtensions.begin(), enabledInstanceExtensions.end(), VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME) == enabledInstanceExtensions.end()) + { + enabledInstanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); + } +#endif #if defined(VK_USE_PLATFORM_MACOS_MVK) && (VK_HEADER_VERSION >= 216) instanceExtensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME); @@ -75,6 +83,14 @@ VkResult VulkanExampleBase::createInstance(bool enableValidation) } } +#if defined(VK_KHR_portability_enumeration) + // SRS - When VK_KHR_portability_enumeration is defined and supported, enable it to properly enumerate the physical device + if (std::find(supportedInstanceExtensions.begin(), supportedInstanceExtensions.end(), VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME) != supportedInstanceExtensions.end()) + { + enabledInstanceExtensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME); + } +#endif + // Enabled requested instance extensions if (enabledInstanceExtensions.size() > 0) { @@ -102,11 +118,19 @@ VkResult VulkanExampleBase::createInstance(bool enableValidation) { if (settings.validation) { + instanceExtensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME); // SRS - Dependency when VK_EXT_DEBUG_MARKER is enabled instanceExtensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); } instanceCreateInfo.enabledExtensionCount = (uint32_t)instanceExtensions.size(); instanceCreateInfo.ppEnabledExtensionNames = instanceExtensions.data(); } +#if defined(VK_KHR_portability_enumeration) + // SRS - When VK_KHR_portability_enumeration is defined and enabled, the VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR flag must be set + if (std::find(instanceExtensions.begin(), instanceExtensions.end(), VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME) != instanceExtensions.end()) + { + instanceCreateInfo.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; + } +#endif // The VK_LAYER_KHRONOS_validation contains all current validation functionality. // Note that on Android this layer requires at least NDK r20 diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index a40dccfb..0876bc24 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -12,15 +12,23 @@ function(buildExample EXAMPLE_NAME) SET(MAIN_HEADER ${EXAMPLE_FOLDER}/${EXAMPLE_NAME}.h) ENDIF() if(APPLE) + # SRS - Use MacPorts paths as default since they are the same on x86 and Apple Silicon, can override on cmake command line + if(NOT OpenMP_omp_LIBRARY) + set(OpenMP_omp_LIBRARY /opt/local/lib/libomp/libomp.dylib) + endif() if(CMAKE_C_COMPILER_ID MATCHES "Clang\$") - set(OpenMP_C_FLAGS "-Xpreprocessor -fopenmp") + set(OpenMP_C_FLAGS "-Xclang -fopenmp") set(OpenMP_C_LIB_NAMES "omp") - set(OpenMP_omp_LIBRARY /opt/local/lib/libomp/libomp.dylib) + if(NOT OpenMP_C_INCLUDE_DIR) + set(OpenMP_C_INCLUDE_DIR /opt/local/include/libomp) + endif() endif() if(CMAKE_CXX_COMPILER_ID MATCHES "Clang\$") - set(OpenMP_CXX_FLAGS "-Xpreprocessor -fopenmp") + set(OpenMP_CXX_FLAGS "-Xclang -fopenmp") set(OpenMP_CXX_LIB_NAMES "omp") - set(OpenMP_omp_LIBRARY /opt/local/lib/libomp/libomp.dylib) + if(NOT OpenMP_CXX_INCLUDE_DIR) + set(OpenMP_CXX_INCLUDE_DIR /opt/local/include/libomp) + endif() endif() endif() find_package(OpenMP) @@ -51,14 +59,15 @@ function(buildExample EXAMPLE_NAME) endif(WIN32) set_target_properties(${EXAMPLE_NAME} PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) - if(OpenMP_CXX_FOUND) - target_compile_options(${EXAMPLE_NAME} PRIVATE ${OpenMP_CXX_FLAGS}) + #if(OpenMP_CXX_FOUND) + # SRS - target_compile_options is not needed when using target_link_libraries( OpenMP::OpenMP_CXX) syntax below + #target_compile_options(${EXAMPLE_NAME} PRIVATE ${OpenMP_CXX_FLAGS}) IF(${EXAMPLE_NAME} STREQUAL "texture3d") if(OpenMP_CXX_FOUND) target_link_libraries(${EXAMPLE_NAME} OpenMP::OpenMP_CXX) endif() endif() - endif() + #endif() if(RESOURCE_INSTALL_DIR) install(TARGETS ${EXAMPLE_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR}) From 8080b7a91b777377619a2f677d643f422d63ede2 Mon Sep 17 00:00:00 2001 From: Stephen Saunders Date: Fri, 13 May 2022 11:58:46 -0400 Subject: [PATCH 12/36] Support iOS touch gestures and iOS Simulator target, reduce translate sensitivity, use key chars vs. key codes in Xcode examples project --- base/vulkanexamplebase.cpp | 2 +- xcode/MVKExample.cpp | 78 +++++++++++++-------- xcode/MVKExample.h | 17 ++--- xcode/examples.h | 7 +- xcode/examples.xcodeproj/project.pbxproj | 24 +++---- xcode/ios/DemoViewController.mm | 87 ++++++++++++++++++++---- xcode/ios/Info.plist | 2 + xcode/macos/DemoViewController.mm | 29 ++++---- xcode/macos/Resources/Main.storyboard | 4 +- 9 files changed, 165 insertions(+), 85 deletions(-) diff --git a/base/vulkanexamplebase.cpp b/base/vulkanexamplebase.cpp index 2e00aa14..28016be2 100644 --- a/base/vulkanexamplebase.cpp +++ b/base/vulkanexamplebase.cpp @@ -2793,7 +2793,7 @@ void VulkanExampleBase::handleMouseMove(int32_t x, int32_t y) viewUpdated = true; } if (mouseButtons.middle) { - camera.translate(glm::vec3(-dx * 0.01f, -dy * 0.01f, 0.0f)); + camera.translate(glm::vec3(-dx * 0.005f, -dy * 0.005f, 0.0f)); viewUpdated = true; } mousePos = glm::vec2((float)x, (float)y); diff --git a/xcode/MVKExample.cpp b/xcode/MVKExample.cpp index 9ed6e36b..ca561249 100644 --- a/xcode/MVKExample.cpp +++ b/xcode/MVKExample.cpp @@ -5,11 +5,14 @@ * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) */ -#include #include "MVKExample.h" #include "examples.h" +void MVKExample::renderFrame() { + _vulkanExample->renderFrame(); +} + void MVKExample::displayLinkOutputCb() { // SRS - expose VulkanExampleBase::displayLinkOutputCb() to DemoViewController _vulkanExample->displayLinkOutputCb(); } @@ -18,26 +21,44 @@ void MVKExample::setRefreshPeriod(double refreshPeriod) { // SRS - set Vul _vulkanExample->refreshPeriod = refreshPeriod; } -void MVKExample::keyPressed(uint32_t keyCode) { - _vulkanExample->keyPressed(keyCode); +void MVKExample::keyPressed(uint32_t keyChar) { // SRS - handle iOS virtual screen keyboard presses + switch (keyChar) + { + case 'p': + case 'P': + _vulkanExample->paused = !_vulkanExample->paused; + break; + default: + _vulkanExample->keyPressed(keyChar); + break; + } } -void MVKExample::keyDown(uint32_t keyCode) { - switch (keyCode) +void MVKExample::keyDown(uint32_t keyChar) { // SRS - handle physical keyboard key down/up actions + switch (keyChar) { - case kVK_ANSI_P: + case 'p': + case 'P': _vulkanExample->paused = !_vulkanExample->paused; break; - case kVK_ANSI_W: + case 'w': + case 'W': + case 'z': // for French AZERTY keyboards + case 'Z': _vulkanExample->camera.keys.up = true; break; - case kVK_ANSI_S: + case 's': + case 'S': _vulkanExample->camera.keys.down = true; break; - case kVK_ANSI_A: + case 'a': + case 'A': + case 'q': // for French AZERTY keyboards + case 'Q': _vulkanExample->camera.keys.left = true; break; - case kVK_ANSI_D: + case 'd': + case 'D': _vulkanExample->camera.keys.right = true; break; default: @@ -45,19 +66,27 @@ void MVKExample::keyDown(uint32_t keyCode) { } } -void MVKExample::keyUp(uint32_t keyCode) { - switch (keyCode) +void MVKExample::keyUp(uint32_t keyChar) { + switch (keyChar) { - case kVK_ANSI_W: + case 'w': + case 'W': + case 'z': // for French AZERTY keyboards + case 'Z': _vulkanExample->camera.keys.up = false; break; - case kVK_ANSI_S: + case 's': + case 'S': _vulkanExample->camera.keys.down = false; break; - case kVK_ANSI_A: + case 'a': + case 'A': + case 'q': // for French AZERTY keyboards + case 'Q': _vulkanExample->camera.keys.left = false; break; - case kVK_ANSI_D: + case 'd': + case 'D': _vulkanExample->camera.keys.right = false; break; default: @@ -70,12 +99,12 @@ void MVKExample::mouseDown(double x, double y) { _vulkanExample->mouseButtons.left = true; } -void MVKExample::mouseUp(double x, double y) { - _vulkanExample->mousePos = glm::vec2(x, y); +void MVKExample::mouseUp() { _vulkanExample->mouseButtons.left = false; } -void MVKExample::rightMouseDown() { +void MVKExample::rightMouseDown(double x, double y) { + _vulkanExample->mousePos = glm::vec2(x, y); _vulkanExample->mouseButtons.right = true; } @@ -83,7 +112,8 @@ void MVKExample::rightMouseUp() { _vulkanExample->mouseButtons.right = false; } -void MVKExample::otherMouseDown() { +void MVKExample::otherMouseDown(double x, double y) { + _vulkanExample->mousePos = glm::vec2(x, y); _vulkanExample->mouseButtons.middle = true; } @@ -95,22 +125,16 @@ void MVKExample::mouseDragged(double x, double y) { _vulkanExample->mouseDragged(x, y); } -void MVKExample::mouseMoved(double x, double y) { - _vulkanExample->mouseDragged(x, y); -} - void MVKExample::scrollWheel(short wheelDelta) { _vulkanExample->camera.translate(glm::vec3(0.0f, 0.0f, wheelDelta * 0.05f * _vulkanExample->camera.movementSpeed)); } MVKExample::MVKExample(void* view) { _vulkanExample = new VulkanExample(); - width = _vulkanExample->width; // SRS - Get desired window size from VulkanExampleBase instance - height = _vulkanExample->height; _vulkanExample->initVulkan(); _vulkanExample->setupWindow(view); _vulkanExample->prepare(); - _vulkanExample->renderLoop(); // SRS - Init destWidth & destHeight, then fall through and return + _vulkanExample->renderLoop(); // SRS - init VulkanExampleBase::destWidth & destHeight, then fall through and return } MVKExample::~MVKExample() { diff --git a/xcode/MVKExample.h b/xcode/MVKExample.h index 8e5acf47..5b647c63 100644 --- a/xcode/MVKExample.h +++ b/xcode/MVKExample.h @@ -13,24 +13,21 @@ class MVKExample { public: - uint32_t width; // SRS - expose VulkanExampleBase initial window size to DemoViewController - uint32_t height; - + void renderFrame(); void displayLinkOutputCb(); // SRS - expose VulkanExampleBase::displayLinkOutputCb() to DemoViewController void setRefreshPeriod(double refreshPeriod); // SRS - set VulkanExampleBase::refreshPeriod from DemoViewController displayLink - void keyPressed(uint32_t keyCode); // SRS - expose keyboard events to DemoViewController - void keyDown(uint32_t keyCode); - void keyUp(uint32_t keyCode); + void keyPressed(uint32_t keyChar); // SRS - expose keyboard events to DemoViewController + void keyDown(uint32_t keyChar); + void keyUp(uint32_t keyChar); void mouseDown(double x, double y); // SRS - expose mouse events to DemoViewController - void mouseUp(double x, double y); - void rightMouseDown(); + void mouseUp(); + void rightMouseDown(double x, double y); void rightMouseUp(); - void otherMouseDown(); + void otherMouseDown(double x, double y); void otherMouseUp(); void mouseDragged(double x, double y); - void mouseMoved(double x, double y); void scrollWheel(short wheelDelta); MVKExample(void* view); diff --git a/xcode/examples.h b/xcode/examples.h index 68182c49..4268deca 100644 --- a/xcode/examples.h +++ b/xcode/examples.h @@ -17,7 +17,7 @@ * * For example, to run the pipelines example, you would add the MVK_pipelines define macro * to the Preprocessor Macros (aka GCC_PREPROCESSOR_DEFINITIONS) entry of the Xcode project, - * overwriting any otheor value there. + * overwriting any other value there. * * If you choose to add a #define statement to this file, be sure to clear the existing macro * from the Preprocessor Macros (aka GCC_PREPROCESSOR_DEFINITIONS) compiler setting in Xcode. @@ -27,11 +27,12 @@ // In the list below, the comments indicate entries that, // under certain conditions, that may not run as expected. -#define MVK_vulkanscene +// Uncomment the next line and select example here if not using a Preprocessor Macro to define example +//#define MVK_vulkanscene // COMMON - Include VulkanglTFModel.cpp in all examples other than ones that already include/customize tiny_gltf.h directly #if !defined(MVK_gltfloading) && !defined(MVK_gltfskinning) && !defined(MVK_gltfscenerendering) && !defined(MVK_vertexattributes) -#include "../base/VulkanglTFModel.cpp" +# include "../base/VulkanglTFModel.cpp" #endif diff --git a/xcode/examples.xcodeproj/project.pbxproj b/xcode/examples.xcodeproj/project.pbxproj index 173ea0da..4b9237ca 100644 --- a/xcode/examples.xcodeproj/project.pbxproj +++ b/xcode/examples.xcodeproj/project.pbxproj @@ -638,12 +638,13 @@ ); GCC_WARN_64_TO_32_BIT_CONVERSION = NO; INFOPLIST_FILE = "$(SRCROOT)/iOS/Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = "@executable_path"; LIBRARY_SEARCH_PATHS = "\"$(SRCROOT)/MoltenVK/dylib/iOS\""; SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; TARGETED_DEVICE_FAMILY = "1,2"; - VALID_ARCHS = arm64; + VALID_ARCHS = "$(ARCHS_STANDARD)"; }; name = Debug; }; @@ -659,12 +660,13 @@ ); GCC_WARN_64_TO_32_BIT_CONVERSION = NO; INFOPLIST_FILE = "$(SRCROOT)/iOS/Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = "@executable_path"; LIBRARY_SEARCH_PATHS = "\"$(SRCROOT)/MoltenVK/dylib/iOS\""; SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; TARGETED_DEVICE_FAMILY = "1,2"; - VALID_ARCHS = arm64; + VALID_ARCHS = "$(ARCHS_STANDARD)"; }; name = Release; }; @@ -676,11 +678,7 @@ COMBINE_HIDPI_IMAGES = YES; GCC_PREFIX_HEADER = ""; GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - _DEBUG, - VK_USE_PLATFORM_MACOS_MVK, - ); - "GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = ( + "$(inherited)", "DEBUG=1", _DEBUG, VK_USE_PLATFORM_MACOS_MVK, @@ -700,13 +698,15 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COMBINE_HIDPI_IMAGES = YES; GCC_PREFIX_HEADER = ""; - GCC_PREPROCESSOR_DEFINITIONS = VK_USE_PLATFORM_MACOS_MVK; - "GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = VK_USE_PLATFORM_MACOS_MVK; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + VK_USE_PLATFORM_MACOS_MVK, + ); INFOPLIST_FILE = "$(SRCROOT)/macOS/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "@executable_path"; LIBRARY_SEARCH_PATHS = "\"$(SRCROOT)/MoltenVK/dylib/macOS\""; MACOSX_DEPLOYMENT_TARGET = 10.11; - ONLY_ACTIVE_ARCH = YES; + ONLY_ACTIVE_ARCH = NO; SDKROOT = macosx; }; name = Release; diff --git a/xcode/ios/DemoViewController.mm b/xcode/ios/DemoViewController.mm index a8d4ca3c..616ba39f 100644 --- a/xcode/ios/DemoViewController.mm +++ b/xcode/ios/DemoViewController.mm @@ -37,13 +37,22 @@ const std::string getAssetPath() { [_displayLink setFrameInterval: 60 / fps]; [_displayLink addToRunLoop: NSRunLoop.currentRunLoop forMode: NSDefaultRunLoopMode]; - // Setup tap gesture to toggle virtual keyboard + // SRS - set VulkanExampleBase::refreshPeriod to calibrate the frame animation rate + _mvkExample->setRefreshPeriod( 1.0 / fps ); + + // Setup double tap gesture to toggle virtual keyboard UITapGestureRecognizer* tapSelector = [[UITapGestureRecognizer alloc] initWithTarget: self action: @selector(handleTapGesture:)]; - tapSelector.numberOfTapsRequired = 1; + tapSelector.numberOfTapsRequired = 2; tapSelector.cancelsTouchesInView = YES; [self.view addGestureRecognizer: tapSelector]; + // SRS - Setup pinch gesture to detect and activate zoom + UIPinchGestureRecognizer* pinchSelector = [[UIPinchGestureRecognizer alloc] + initWithTarget: self action: @selector(handlePinchGesture:)]; + pinchSelector.cancelsTouchesInView = YES; + [self.view addGestureRecognizer: pinchSelector]; + _viewHasAppeared = NO; } @@ -55,8 +64,8 @@ const std::string getAssetPath() { -(BOOL) canBecomeFirstResponder { return _viewHasAppeared; } -(void) renderFrame { - //_mvkExample->renderFrame(); - _mvkExample->nextFrame(); // SRS - Call MVKExample::nextFrame() to animate frames vs. MVKExample::renderFrame() for static image + //_mvkExample->renderFrame(); + _mvkExample->displayLinkOutputCb(); // SRS - Call displayLinkOutputCb() to animate frames vs. renderFrame() for static image } -(void) dealloc { @@ -73,18 +82,13 @@ const std::string getAssetPath() { } } -// Display and hide the keyboard by tapping on the view +// Display and hide the keyboard by double tapping on the view -(void) handleTapGesture: (UITapGestureRecognizer*) gestureRecognizer { if (gestureRecognizer.state == UIGestureRecognizerStateEnded) { [self toggleKeyboard]; } } -// Handle keyboard input --(void) handleKeyboardInput: (unichar) keycode { - _mvkExample->keyPressed(keycode); -} - #pragma mark UIKeyInput methods @@ -93,16 +97,73 @@ const std::string getAssetPath() { // A key on the keyboard has been pressed. -(void) insertText: (NSString*) text { - unichar keycode = (text.length > 0) ? [text characterAtIndex: 0] : 0; - [self handleKeyboardInput: keycode]; + unichar keychar = (text.length > 0) ? [text characterAtIndex: 0] : 0; + _mvkExample->keyPressed(keychar); } // The delete backward key has been pressed. -(void) deleteBackward { - [self handleKeyboardInput: 0x33]; + _mvkExample->keyPressed(0x7F); } +#pragma mark UITouch methods + +// SRS - Handle touch events +-(CGPoint) getTouchLocalPoint:(UIEvent*) theEvent { + UITouch *touch = [[theEvent allTouches] anyObject]; + CGPoint point = [touch locationInView:self.view]; + point.x = point.x * self.view.contentScaleFactor; + point.y = point.y * self.view.contentScaleFactor; + return point; +} + +-(void) touchesBegan:(NSSet*) touches withEvent:(UIEvent*) theEvent { + auto point = [self getTouchLocalPoint:theEvent]; + if (touches.count == 1) { + // Single touch for imgui select and camera rotation + _mvkExample->mouseDown(point.x, point.y); + } + else { + // Multi-touch for swipe translation (note: pinch gesture will cancel/override) + _mvkExample->otherMouseDown(point.x, point.y); + } +} + +-(void) touchesMoved:(NSSet*) touches withEvent:(UIEvent*) theEvent { + auto point = [self getTouchLocalPoint:theEvent]; + _mvkExample->mouseDragged(point.x, point.y); +} + +-(void) touchesEnded:(NSSet*) touches withEvent:(UIEvent*) theEvent { + _mvkExample->mouseUp(); + _mvkExample->otherMouseUp(); +} + +-(void) touchesCancelled:(NSSet*) touches withEvent:(UIEvent*) theEvent { + _mvkExample->mouseUp(); + _mvkExample->otherMouseUp(); +} + +// SRS - Respond to pinch gestures for zoom +-(void) handlePinchGesture: (UIPinchGestureRecognizer*) gestureRecognizer { + if (gestureRecognizer.state == UIGestureRecognizerStateBegan) { + auto point = [gestureRecognizer locationInView:self.view]; + point.x = point.x * self.view.contentScaleFactor; + point.y = point.y * self.view.contentScaleFactor; + _mvkExample->rightMouseDown(point.x, point.y); + } + else if (gestureRecognizer.state == UIGestureRecognizerStateChanged) { + auto point = [gestureRecognizer locationInView:self.view]; + point.x = point.x * self.view.contentScaleFactor; + point.y = point.y * self.view.contentScaleFactor; + _mvkExample->mouseDragged(point.x, point.y - gestureRecognizer.view.frame.size.height / 2.0 * log(gestureRecognizer.scale)); + } + else if (gestureRecognizer.state == UIGestureRecognizerStateEnded) { + _mvkExample->rightMouseUp(); + } +} + @end diff --git a/xcode/ios/Info.plist b/xcode/ios/Info.plist index eb0fa65a..e61fdb6f 100644 --- a/xcode/ios/Info.plist +++ b/xcode/ios/Info.plist @@ -20,6 +20,8 @@ APPL CFBundleVersion 1.0 + CFBundleShortVersionString + 1.0 LSApplicationCategoryType UIMainStoryboardFile diff --git a/xcode/macos/DemoViewController.mm b/xcode/macos/DemoViewController.mm index c1e3cf1d..ea33c1bd 100644 --- a/xcode/macos/DemoViewController.mm +++ b/xcode/macos/DemoViewController.mm @@ -48,15 +48,11 @@ MVKExample* _mvkExample; CVDisplayLinkStart(_displayLink); } -// SRS - Set window's initial content size and set VulkanExampleBase::refreshPeriod from the displayLink +// SRS - Center the window and set VulkanExampleBase::refreshPeriod from the active displayLink -(void) viewWillAppear { [super viewWillAppear]; NSWindow* window = self.view.window; - NSSize viewSize; - viewSize.width = _mvkExample->width; - viewSize.height = _mvkExample->height; - [window setContentSize:viewSize]; [window center]; _mvkExample->setRefreshPeriod(CVDisplayLinkGetActualOutputVideoRefreshPeriod(_displayLink)); @@ -94,12 +90,15 @@ MVKExample* _mvkExample; // SRS - Handle keyboard events -(void) keyDown:(NSEvent*) theEvent { - _mvkExample->keyPressed(theEvent.keyCode); - _mvkExample->keyDown(theEvent.keyCode); + NSString *text = [theEvent charactersIgnoringModifiers]; + unichar keychar = (text.length > 0) ? [text characterAtIndex: 0] : 0; + _mvkExample->keyDown(keychar); } -(void) keyUp:(NSEvent*) theEvent { - _mvkExample->keyUp(theEvent.keyCode); + NSString *text = [theEvent charactersIgnoringModifiers]; + unichar keychar = (text.length > 0) ? [text characterAtIndex: 0] : 0; + _mvkExample->keyUp(keychar); } // SRS - Handle mouse events @@ -116,12 +115,12 @@ MVKExample* _mvkExample; } -(void) mouseUp:(NSEvent*) theEvent { - auto point = [self getMouseLocalPoint:theEvent]; - _mvkExample->mouseUp(point.x, point.y); + _mvkExample->mouseUp(); } -(void) rightMouseDown:(NSEvent*) theEvent { - _mvkExample->rightMouseDown(); + auto point = [self getMouseLocalPoint:theEvent]; + _mvkExample->rightMouseDown(point.x, point.y); } -(void) rightMouseUp:(NSEvent*) theEvent { @@ -129,7 +128,8 @@ MVKExample* _mvkExample; } -(void) otherMouseDown:(NSEvent*) theEvent { - _mvkExample->otherMouseDown(); + auto point = [self getMouseLocalPoint:theEvent]; + _mvkExample->otherMouseDown(point.x, point.y); } -(void) otherMouseUp:(NSEvent*) theEvent { @@ -151,11 +151,6 @@ MVKExample* _mvkExample; _mvkExample->mouseDragged(point.x, point.y); } --(void) mouseMoved:(NSEvent*) theEvent { - auto point = [self getMouseLocalPoint:theEvent]; - _mvkExample->mouseDragged(point.x, point.y); -} - -(void) scrollWheel:(NSEvent*) theEvent { short wheelDelta = [theEvent deltaY]; _mvkExample->scrollWheel(wheelDelta); diff --git a/xcode/macos/Resources/Main.storyboard b/xcode/macos/Resources/Main.storyboard index e682969c..6ba73adf 100644 --- a/xcode/macos/Resources/Main.storyboard +++ b/xcode/macos/Resources/Main.storyboard @@ -103,7 +103,7 @@ - + @@ -122,7 +122,7 @@ - + From a1e19ea5def5bab6bd832c230c3c237afccffe09 Mon Sep 17 00:00:00 2001 From: Stephen Saunders Date: Fri, 13 May 2022 21:57:30 -0400 Subject: [PATCH 13/36] Fix iOS/macOS keycode handling regression for textoverlay example, update and use keycodes.hpp defines for iOS/macOS --- base/keycodes.hpp | 28 +++++++++++------- base/vulkanexamplebase.cpp | 8 ++++-- xcode/MVKExample.cpp | 48 +++++++++++-------------------- xcode/ios/DemoViewController.mm | 4 +-- xcode/macos/DemoViewController.mm | 4 +-- 5 files changed, 43 insertions(+), 49 deletions(-) diff --git a/base/keycodes.hpp b/base/keycodes.hpp index d9d7f654..73f383ea 100644 --- a/base/keycodes.hpp +++ b/base/keycodes.hpp @@ -40,11 +40,12 @@ #define GAMEPAD_BUTTON_START 0x1006 #define TOUCH_DOUBLE_TAP 0x1100 -#elif defined(VK_USE_PLATFORM_IOS_MVK) -// Use numeric keys instead of function keys. -// Use main keyboard plus/minus instead of keypad plus/minus -// Use Delete key instead of Escape key. -#define KEY_ESCAPE 0x33 +#elif (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK)) +#if !defined(VK_EXAMPLE_XCODE_GENERATED) +// For iOS and macOS pre-configured Xcode example project: Use character keycodes +// - Use numeric keys instead of function keys. +#define KEY_DELETE 0x7F +#define KEY_ESCAPE 0x1B #define KEY_F1 '1' #define KEY_F2 '2' #define KEY_F3 '3' @@ -62,14 +63,18 @@ #define KEY_L 'l' #define KEY_N 'n' #define KEY_O 'o' +#define KEY_Q 'q' #define KEY_T 't' +#define KEY_Z 'z' -#elif defined(VK_USE_PLATFORM_MACOS_MVK) -// For compatibility with iOS UX and absent keypad on MacBook: +#else // defined(VK_EXAMPLE_XCODE_GENERATED) +// For cross-platform cmake-generated Xcode project: Use ANSI keyboard keycodes // - Use numeric keys instead of function keys // - Use main keyboard plus/minus instead of keypad plus/minus -// - Use Delete key instead of Escape key -#define KEY_ESCAPE 0x33 +// Note: Carbon kVK_* definitions are used instead of these in vulkanexamplebase.cpp +// Currently only KEY_SPACE and KEY_KPADD are used in textoverlay.cpp example +#define KEY_DELETE 0x33 +#define KEY_ESCAPE 0x35 #define KEY_F1 0x12 #define KEY_F2 0x13 #define KEY_F3 0x14 @@ -87,7 +92,10 @@ #define KEY_L 0x25 #define KEY_N 0x2D #define KEY_O 0x1F +#define KEY_Q 0x0C #define KEY_T 0x11 +#define KEY_Z 0x06 +#endif #elif defined(VK_USE_PLATFORM_DIRECTFB_EXT) #define KEY_ESCAPE DIKS_ESCAPE @@ -137,4 +145,4 @@ #define KEY_N 0x39 #define KEY_O 0x20 #define KEY_T 0x1C -#endif \ No newline at end of file +#endif diff --git a/base/vulkanexamplebase.cpp b/base/vulkanexamplebase.cpp index 28016be2..bbafb239 100644 --- a/base/vulkanexamplebase.cpp +++ b/base/vulkanexamplebase.cpp @@ -1601,6 +1601,7 @@ static CVReturn displayLinkOutputCallback(CVDisplayLinkRef displayLink, const CV case kVK_ANSI_P: vulkanExample->paused = !vulkanExample->paused; break; + case kVK_Delete: // support keyboards with no escape key case kVK_Escape: [NSApp terminate:nil]; break; @@ -1617,6 +1618,7 @@ static CVReturn displayLinkOutputCallback(CVDisplayLinkRef displayLink, const CV vulkanExample->camera.keys.right = true; break; default: + vulkanExample->keyPressed(event.keyCode); // handle example-specific key press events break; } } @@ -1633,9 +1635,9 @@ static CVReturn displayLinkOutputCallback(CVDisplayLinkRef displayLink, const CV break; case kVK_ANSI_A: vulkanExample->camera.keys.left = false; - break; - case kVK_ANSI_D: - vulkanExample->camera.keys.right = false; + break; + case kVK_ANSI_D: + vulkanExample->camera.keys.right = false; break; default: break; diff --git a/xcode/MVKExample.cpp b/xcode/MVKExample.cpp index ca561249..53c73a23 100644 --- a/xcode/MVKExample.cpp +++ b/xcode/MVKExample.cpp @@ -21,11 +21,10 @@ void MVKExample::setRefreshPeriod(double refreshPeriod) { // SRS - set Vul _vulkanExample->refreshPeriod = refreshPeriod; } -void MVKExample::keyPressed(uint32_t keyChar) { // SRS - handle iOS virtual screen keyboard presses +void MVKExample::keyPressed(uint32_t keyChar) { // SRS - handle keyboard key presses only (e.g. Pause, Space, etc) switch (keyChar) { - case 'p': - case 'P': + case KEY_P: _vulkanExample->paused = !_vulkanExample->paused; break; default: @@ -34,34 +33,25 @@ void MVKExample::keyPressed(uint32_t keyChar) { // SRS - handle iOS virtual } } -void MVKExample::keyDown(uint32_t keyChar) { // SRS - handle physical keyboard key down/up actions +void MVKExample::keyDown(uint32_t keyChar) { // SRS - handle physical keyboard key down/up actions and presses switch (keyChar) { - case 'p': - case 'P': - _vulkanExample->paused = !_vulkanExample->paused; - break; - case 'w': - case 'W': - case 'z': // for French AZERTY keyboards - case 'Z': + case KEY_W: + case KEY_Z: // for French AZERTY keyboards _vulkanExample->camera.keys.up = true; break; - case 's': - case 'S': + case KEY_S: _vulkanExample->camera.keys.down = true; break; - case 'a': - case 'A': - case 'q': // for French AZERTY keyboards - case 'Q': + case KEY_A: + case KEY_Q: // for French AZERTY keyboards _vulkanExample->camera.keys.left = true; break; - case 'd': - case 'D': + case KEY_D: _vulkanExample->camera.keys.right = true; break; default: + MVKExample::keyPressed(keyChar); break; } } @@ -69,24 +59,18 @@ void MVKExample::keyDown(uint32_t keyChar) { // SRS - handle physical keyboa void MVKExample::keyUp(uint32_t keyChar) { switch (keyChar) { - case 'w': - case 'W': - case 'z': // for French AZERTY keyboards - case 'Z': + case KEY_W: + case KEY_Z: // for French AZERTY keyboards _vulkanExample->camera.keys.up = false; break; - case 's': - case 'S': + case KEY_S: _vulkanExample->camera.keys.down = false; break; - case 'a': - case 'A': - case 'q': // for French AZERTY keyboards - case 'Q': + case KEY_A: + case KEY_Q: // for French AZERTY keyboards _vulkanExample->camera.keys.left = false; break; - case 'd': - case 'D': + case KEY_D: _vulkanExample->camera.keys.right = false; break; default: diff --git a/xcode/ios/DemoViewController.mm b/xcode/ios/DemoViewController.mm index 616ba39f..2fa3d098 100644 --- a/xcode/ios/DemoViewController.mm +++ b/xcode/ios/DemoViewController.mm @@ -97,13 +97,13 @@ const std::string getAssetPath() { // A key on the keyboard has been pressed. -(void) insertText: (NSString*) text { - unichar keychar = (text.length > 0) ? [text characterAtIndex: 0] : 0; + unichar keychar = (text.length > 0) ? [text.lowercaseString characterAtIndex: 0] : 0; _mvkExample->keyPressed(keychar); } // The delete backward key has been pressed. -(void) deleteBackward { - _mvkExample->keyPressed(0x7F); + _mvkExample->keyPressed(KEY_DELETE); } diff --git a/xcode/macos/DemoViewController.mm b/xcode/macos/DemoViewController.mm index ea33c1bd..333e0fe0 100644 --- a/xcode/macos/DemoViewController.mm +++ b/xcode/macos/DemoViewController.mm @@ -91,13 +91,13 @@ MVKExample* _mvkExample; // SRS - Handle keyboard events -(void) keyDown:(NSEvent*) theEvent { NSString *text = [theEvent charactersIgnoringModifiers]; - unichar keychar = (text.length > 0) ? [text characterAtIndex: 0] : 0; + unichar keychar = (text.length > 0) ? [text.lowercaseString characterAtIndex: 0] : 0; _mvkExample->keyDown(keychar); } -(void) keyUp:(NSEvent*) theEvent { NSString *text = [theEvent charactersIgnoringModifiers]; - unichar keychar = (text.length > 0) ? [text characterAtIndex: 0] : 0; + unichar keychar = (text.length > 0) ? [text.lowercaseString characterAtIndex: 0] : 0; _mvkExample->keyUp(keychar); } From cb343c329a7580954eebf2b7c68bc7f6e10a56ba Mon Sep 17 00:00:00 2001 From: Stephen Saunders Date: Wed, 1 Jun 2022 12:46:41 -0400 Subject: [PATCH 14/36] Fixes for vulkanExample: frame timing now equals diff between frames for Win & macOS portability, support vsync off rendering on macOS, support swapchain image count change on resize, handle macOS fullscreen; Fixes for xcode example: use PanGestureRecognizer on iOS, add macOS cursor tracking, cleanup Vulkan on shutdown --- base/VulkanSwapChain.cpp | 9 ++- base/VulkanSwapChain.h | 2 +- base/vulkanexamplebase.cpp | 100 +++++++++++++++++++------ base/vulkanexamplebase.h | 7 +- xcode/MVKExample.cpp | 11 +-- xcode/MVKExample.h | 5 +- xcode/examples.h | 6 +- xcode/ios/AppDelegate.h | 1 + xcode/ios/AppDelegate.m | 2 + xcode/ios/DemoViewController.h | 1 + xcode/ios/DemoViewController.mm | 117 ++++++++++++++++++++---------- xcode/macos/AppDelegate.h | 2 + xcode/macos/AppDelegate.m | 2 + xcode/macos/DemoViewController.h | 1 + xcode/macos/DemoViewController.mm | 43 ++++++++--- 15 files changed, 222 insertions(+), 87 deletions(-) diff --git a/base/VulkanSwapChain.cpp b/base/VulkanSwapChain.cpp index 432fee10..9d2f92b5 100644 --- a/base/VulkanSwapChain.cpp +++ b/base/VulkanSwapChain.cpp @@ -229,7 +229,7 @@ void VulkanSwapChain::connect(VkInstance instance, VkPhysicalDevice physicalDevi * @param height Pointer to the height of the swapchain (may be adjusted to fit the requirements of the swapchain) * @param vsync (Optional) Can be used to force vsync-ed rendering (by using VK_PRESENT_MODE_FIFO_KHR as presentation mode) */ -void VulkanSwapChain::create(uint32_t *width, uint32_t *height, bool vsync) +void VulkanSwapChain::create(uint32_t *width, uint32_t *height, bool vsync, bool fullscreen) { // Store the current swap chain handle so we can use it later on to ease up recreation VkSwapchainKHR oldSwapchain = swapChain; @@ -290,6 +290,13 @@ void VulkanSwapChain::create(uint32_t *width, uint32_t *height, bool vsync) // Determine the number of images uint32_t desiredNumberOfSwapchainImages = surfCaps.minImageCount + 1; +#if (defined(VK_USE_PLATFORM_MACOS_MVK) && defined(VK_EXAMPLE_XCODE_GENERATED)) + // SRS - Work around known MoltenVK issue re 2x frame rate when vsync (VK_PRESENT_MODE_FIFO_KHR) enabled in windowed mode + if (vsync && !fullscreen) + { + desiredNumberOfSwapchainImages = surfCaps.minImageCount; + } +#endif if ((surfCaps.maxImageCount > 0) && (desiredNumberOfSwapchainImages > surfCaps.maxImageCount)) { desiredNumberOfSwapchainImages = surfCaps.maxImageCount; diff --git a/base/VulkanSwapChain.h b/base/VulkanSwapChain.h index 686bf498..29eaeb1b 100644 --- a/base/VulkanSwapChain.h +++ b/base/VulkanSwapChain.h @@ -73,7 +73,7 @@ public: #endif #endif void connect(VkInstance instance, VkPhysicalDevice physicalDevice, VkDevice device); - void create(uint32_t* width, uint32_t* height, bool vsync = false); + void create(uint32_t* width, uint32_t* height, bool vsync = false, bool fullscreen = false); VkResult acquireNextImage(VkSemaphore presentCompleteSemaphore, uint32_t* imageIndex); VkResult queuePresent(VkQueue queue, uint32_t imageIndex, VkSemaphore waitSemaphore = VK_NULL_HANDLE); void cleanup(); diff --git a/base/vulkanexamplebase.cpp b/base/vulkanexamplebase.cpp index bbafb239..b25dc05c 100644 --- a/base/vulkanexamplebase.cpp +++ b/base/vulkanexamplebase.cpp @@ -255,7 +255,7 @@ VkPipelineShaderStageCreateInfo VulkanExampleBase::loadShader(std::string fileNa void VulkanExampleBase::nextFrame() { - auto tStart = std::chrono::high_resolution_clock::now(); + //auto tStart = std::chrono::high_resolution_clock::now(); if (viewUpdated) { viewUpdated = false; @@ -265,12 +265,10 @@ void VulkanExampleBase::nextFrame() render(); frameCounter++; auto tEnd = std::chrono::high_resolution_clock::now(); - auto tDiff = std::chrono::duration(tEnd - tStart).count(); -#if (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK)) - frameTimer = (float)tDiff * refreshPeriod; // SRS - Multiply by refresh period due to displayLink callback rendering on iOS and macOS -#else + // SRS - Calculate tDiff as time between frames vs. rendering time for Win32/macOS/iOS vsync portability + //auto tDiff = std::chrono::duration(tEnd - tStart).count(); + auto tDiff = std::chrono::duration(tEnd - tPrevEnd).count(); frameTimer = (float)tDiff / 1000.0f; -#endif camera.update(frameTimer); if (camera.moving()) { @@ -298,6 +296,8 @@ void VulkanExampleBase::nextFrame() frameCounter = 0; lastTimestamp = tEnd; } + tPrevEnd = tEnd; + // TODO: Cap UI overlay update rates updateOverlay(); } @@ -316,6 +316,7 @@ void VulkanExampleBase::renderLoop() destWidth = width; destHeight = height; lastTimestamp = std::chrono::high_resolution_clock::now(); + tPrevEnd = lastTimestamp; #if defined(_WIN32) MSG msg; bool quitMessageReceived = false; @@ -733,9 +734,12 @@ void VulkanExampleBase::prepareFrame() { // Acquire the next image from the swap chain VkResult result = swapChain.acquireNextImage(semaphores.presentComplete, ¤tBuffer); - // Recreate the swapchain if it's no longer compatible with the surface (OUT_OF_DATE) or no longer optimal for presentation (SUBOPTIMAL) + // Recreate the swapchain if it's no longer compatible with the surface (OUT_OF_DATE) + // SRS - If no longer optimal (VK_SUBOPTIMAL_KHR), wait until submitFrame() in case number of swapchain images will change on resize if ((result == VK_ERROR_OUT_OF_DATE_KHR) || (result == VK_SUBOPTIMAL_KHR)) { - windowResize(); + if (result == VK_ERROR_OUT_OF_DATE_KHR) { + windowResize(); + } } else { VK_CHECK_RESULT(result); @@ -745,15 +749,16 @@ void VulkanExampleBase::prepareFrame() void VulkanExampleBase::submitFrame() { VkResult result = swapChain.queuePresent(queue, currentBuffer, semaphores.renderComplete); - if (!((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR))) { + // Recreate the swapchain if it's no longer compatible with the surface (OUT_OF_DATE) or no longer optimal for presentation (SUBOPTIMAL) + if ((result == VK_ERROR_OUT_OF_DATE_KHR) || (result == VK_SUBOPTIMAL_KHR)) { + windowResize(); if (result == VK_ERROR_OUT_OF_DATE_KHR) { - // Swap chain is no longer compatible with the surface and needs to be recreated - windowResize(); return; - } else { - VK_CHECK_RESULT(result); } } + else { + VK_CHECK_RESULT(result); + } VK_CHECK_RESULT(vkQueueWaitIdle(queue)); } @@ -1524,6 +1529,8 @@ void VulkanExampleBase::handleAppCommand(android_app * app, int32_t cmd) #if defined(VK_EXAMPLE_XCODE_GENERATED) @interface AppDelegate : NSObject { +@public + VulkanExampleBase *vulkanExample; } @end @@ -1532,11 +1539,35 @@ void VulkanExampleBase::handleAppCommand(android_app * app, int32_t cmd) { } +// SRS - Dispatch rendering loop onto a queue for max frame rate concurrent rendering vs displayLink vsync rendering +// - vsync command line option (-vs) on macOS now works like other platforms (using VK_PRESENT_MODE_FIFO_KHR) +dispatch_group_t concurrentGroup; + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification +{ + concurrentGroup = dispatch_group_create(); + dispatch_queue_t concurrentQueue = dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0); + dispatch_group_async(concurrentGroup, concurrentQueue, ^{ + + while (!vulkanExample->quit) { + vulkanExample->displayLinkOutputCb(); + } + }); +} + - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender { return YES; } +// SRS - Tell rendering loop to quit, then wait for concurrent queue to terminate before deleting vulkanExample +- (void)applicationWillTerminate:(NSNotification *)aNotification +{ + vulkanExample->quit = YES; + dispatch_group_wait(concurrentGroup, DISPATCH_TIME_FOREVER); + delete vulkanExample; +} + @end const std::string getAssetPath() { @@ -1582,11 +1613,10 @@ static CVReturn displayLinkOutputCallback(CVDisplayLinkRef displayLink, const CV - (void)viewDidMoveToWindow { CVDisplayLinkCreateWithActiveCGDisplays(&displayLink); - CVDisplayLinkSetOutputCallback(displayLink, &displayLinkOutputCallback, vulkanExample); + // SRS - Disable displayLink vsync rendering in favour of max frame rate concurrent rendering + // - vsync command line option (-vs) on macOS now works like other platforms (using VK_PRESENT_MODE_FIFO_KHR) + //CVDisplayLinkSetOutputCallback(displayLink, &displayLinkOutputCallback, vulkanExample); CVDisplayLinkStart(displayLink); - // SRS - Pause 1 ms for displayLink startup then get the actual refresh period of the display - usleep(1000); - vulkanExample->refreshPeriod = CVDisplayLinkGetActualOutputVideoRefreshPeriod(displayLink); } - (BOOL)acceptsFirstResponder @@ -1661,13 +1691,13 @@ static CVReturn displayLinkOutputCallback(CVDisplayLinkRef displayLink, const CV - (void)mouseUp:(NSEvent *)event { - auto point = [self getMouseLocalPoint:event]; - vulkanExample->mousePos = glm::vec2(point.x, point.y); vulkanExample->mouseButtons.left = false; } - (void)rightMouseDown:(NSEvent *)event { + auto point = [self getMouseLocalPoint:event]; + vulkanExample->mousePos = glm::vec2(point.x, point.y); vulkanExample->mouseButtons.right = true; } @@ -1678,6 +1708,8 @@ static CVReturn displayLinkOutputCallback(CVDisplayLinkRef displayLink, const CV - (void)otherMouseDown:(NSEvent *)event { + auto point = [self getMouseLocalPoint:event]; + vulkanExample->mousePos = glm::vec2(point.x, point.y); vulkanExample->mouseButtons.middle = true; } @@ -1717,6 +1749,9 @@ static CVReturn displayLinkOutputCallback(CVDisplayLinkRef displayLink, const CV -(float)wheelDelta * 0.05f * vulkanExample->camera.movementSpeed)); } +// SRS - Window resizing already handled by windowResize() in VulkanExampleBase::submitFrame() +// - handling window resize events here is redundant and can cause interaction problems +/* - (NSSize)windowWillResize:(NSWindow *)sender toSize:(NSSize)frameSize { CVDisplayLinkStop(displayLink); @@ -1729,6 +1764,17 @@ static CVReturn displayLinkOutputCallback(CVDisplayLinkRef displayLink, const CV vulkanExample->windowDidResize(); CVDisplayLinkStart(displayLink); } +*/ + +- (void)windowWillEnterFullScreen:(NSNotification *)notification +{ + vulkanExample->settings.fullscreen = true; +} + +- (void)windowWillExitFullScreen:(NSNotification *)notification +{ + vulkanExample->settings.fullscreen = false; +} - (BOOL)windowShouldClose:(NSWindow *)sender { @@ -1738,6 +1784,7 @@ static CVReturn displayLinkOutputCallback(CVDisplayLinkRef displayLink, const CV - (void)windowWillClose:(NSNotification *)notification { CVDisplayLinkStop(displayLink); + CVDisplayLinkRelease(displayLink); } @end @@ -1748,7 +1795,9 @@ void* VulkanExampleBase::setupWindow(void* view) #if defined(VK_EXAMPLE_XCODE_GENERATED) NSApp = [NSApplication sharedApplication]; [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; - [NSApp setDelegate:[AppDelegate new]]; + auto nsAppDelegate = [AppDelegate new]; + nsAppDelegate->vulkanExample = this; + [NSApp setDelegate:nsAppDelegate]; const auto kContentRect = NSMakeRect(0.0f, 0.0f, width, height); const auto kWindowStyle = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable; @@ -1761,6 +1810,9 @@ void* VulkanExampleBase::setupWindow(void* view) [window setAcceptsMouseMovedEvents:YES]; [window center]; [window makeKeyAndOrderFront:nil]; + if (settings.fullscreen) { + [window toggleFullScreen:nil]; + } auto nsView = [[View alloc] initWithFrame:kContentRect]; nsView->vulkanExample = this; @@ -2754,6 +2806,12 @@ void VulkanExampleBase::windowResize() destroyCommandBuffers(); createCommandBuffers(); buildCommandBuffers(); + + // SRS - Recreate fences in case number of swapchain images has changed on resize + for (auto& fence : waitFences) { + vkDestroyFence(device, fence, nullptr); + } + createSynchronizationPrimitives(); vkDeviceWaitIdle(device); @@ -2824,7 +2882,7 @@ void VulkanExampleBase::initSwapchain() void VulkanExampleBase::setupSwapChain() { - swapChain.create(&width, &height, settings.vsync); + swapChain.create(&width, &height, settings.vsync, settings.fullscreen); } void VulkanExampleBase::OnUpdateUIOverlay(vks::UIOverlay *overlay) {} diff --git a/base/vulkanexamplebase.h b/base/vulkanexamplebase.h index 4d5befcd..6d5b28b8 100644 --- a/base/vulkanexamplebase.h +++ b/base/vulkanexamplebase.h @@ -119,7 +119,7 @@ protected: // Frame counter to display fps uint32_t frameCounter = 0; uint32_t lastFPS = 0; - std::chrono::time_point lastTimestamp; + std::chrono::time_point lastTimestamp, tPrevEnd; // Vulkan instance, stores all per-application states VkInstance instance; std::vector supportedInstanceExtensions; @@ -254,7 +254,9 @@ public: int64_t lastTapTime = 0; #elif (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK)) void* view; - double refreshPeriod = 1.0/60.0; // SRS - default refreshPeriod for 60 fps display +#if defined(VK_EXAMPLE_XCODE_GENERATED) + bool quit = false; +#endif #elif defined(VK_USE_PLATFORM_DIRECTFB_EXT) bool quit = false; IDirectFB *dfb = nullptr; @@ -534,7 +536,6 @@ int main(const int argc, const char *argv[]) \ vulkanExample->setupWindow(nullptr); \ vulkanExample->prepare(); \ vulkanExample->renderLoop(); \ - delete(vulkanExample); \ } \ return 0; \ } diff --git a/xcode/MVKExample.cpp b/xcode/MVKExample.cpp index 53c73a23..b4f5abb1 100644 --- a/xcode/MVKExample.cpp +++ b/xcode/MVKExample.cpp @@ -17,10 +17,6 @@ void MVKExample::displayLinkOutputCb() { // SRS - expose _vulkanExample->displayLinkOutputCb(); } -void MVKExample::setRefreshPeriod(double refreshPeriod) { // SRS - set VulkanExampleBase::refreshPeriod from DemoViewController displayLink - _vulkanExample->refreshPeriod = refreshPeriod; -} - void MVKExample::keyPressed(uint32_t keyChar) { // SRS - handle keyboard key presses only (e.g. Pause, Space, etc) switch (keyChar) { @@ -113,12 +109,17 @@ void MVKExample::scrollWheel(short wheelDelta) { _vulkanExample->camera.translate(glm::vec3(0.0f, 0.0f, wheelDelta * 0.05f * _vulkanExample->camera.movementSpeed)); } +void MVKExample::fullScreen(bool fullscreen) { + _vulkanExample->settings.fullscreen = fullscreen; +} + MVKExample::MVKExample(void* view) { _vulkanExample = new VulkanExample(); + _vulkanExample->settings.vsync = true; // SRS - this iOS/macOS example uses displayLink vsync rendering - set before calling prepare() _vulkanExample->initVulkan(); _vulkanExample->setupWindow(view); _vulkanExample->prepare(); - _vulkanExample->renderLoop(); // SRS - init VulkanExampleBase::destWidth & destHeight, then fall through and return + _vulkanExample->renderLoop(); // SRS - this inits destWidth/destHeight/lastTimestamp/tPrevEnd, then falls through and returns } MVKExample::~MVKExample() { diff --git a/xcode/MVKExample.h b/xcode/MVKExample.h index 5b647c63..c505a96d 100644 --- a/xcode/MVKExample.h +++ b/xcode/MVKExample.h @@ -15,7 +15,6 @@ class MVKExample { public: void renderFrame(); void displayLinkOutputCb(); // SRS - expose VulkanExampleBase::displayLinkOutputCb() to DemoViewController - void setRefreshPeriod(double refreshPeriod); // SRS - set VulkanExampleBase::refreshPeriod from DemoViewController displayLink void keyPressed(uint32_t keyChar); // SRS - expose keyboard events to DemoViewController void keyDown(uint32_t keyChar); @@ -29,7 +28,9 @@ public: void otherMouseUp(); void mouseDragged(double x, double y); void scrollWheel(short wheelDelta); - + + void fullScreen(bool fullscreen); // SRS - expose VulkanExampleBase::settings.fullscreen to DemoView (macOS only) + MVKExample(void* view); ~MVKExample(); diff --git a/xcode/examples.h b/xcode/examples.h index 4268deca..c6107e4f 100644 --- a/xcode/examples.h +++ b/xcode/examples.h @@ -114,7 +114,7 @@ # include "../examples/particlefire/particlefire.cpp" #endif -// Build issue when using this xcode examples project, builds/runs fine using vulkanExamples project. +// No headless target when using xcode examples project, builds/runs fine using vulkanExamples project. #ifdef MVK_renderheadless # include "../examples/renderheadless/renderheadless.cpp" #endif @@ -191,7 +191,7 @@ # include "../examples/vertexattributes/vertexattributes.cpp" #endif -// Runs but nothing displays. MoltenVK format VK_FORMAT_R32_UINT doesn't contain VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT +// Does not run. MoltenVK/Metal does not support stores and atomic operations in the fragment stage. #ifdef MVK_oit # include "../examples/oit/oit.cpp" #endif @@ -297,7 +297,7 @@ # include "../examples/computecloth/computecloth.cpp" #endif -// Build issue when using this xcode examples project, builds/runs fine using vulkanExamples project. +// No headless target when using xcode examples project, builds/runs fine using vulkanExamples project. #ifdef MVK_computeheadless # include "../examples/computeheadless/computeheadless.cpp" #endif diff --git a/xcode/ios/AppDelegate.h b/xcode/ios/AppDelegate.h index 5023d3dd..02bc20ab 100644 --- a/xcode/ios/AppDelegate.h +++ b/xcode/ios/AppDelegate.h @@ -10,6 +10,7 @@ @interface AppDelegate : UIResponder @property (strong, nonatomic) UIWindow *window; +@property (strong, nonatomic) UIViewController *viewController; @end diff --git a/xcode/ios/AppDelegate.m b/xcode/ios/AppDelegate.m index 8d69ac3b..430a9591 100644 --- a/xcode/ios/AppDelegate.m +++ b/xcode/ios/AppDelegate.m @@ -6,6 +6,7 @@ */ #import "AppDelegate.h" +#import "DemoViewController.h" @interface AppDelegate () @@ -39,6 +40,7 @@ - (void)applicationWillTerminate:(UIApplication *)application { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. + [(DemoViewController *)_viewController shutdownExample]; } @end diff --git a/xcode/ios/DemoViewController.h b/xcode/ios/DemoViewController.h index 81d04021..bc908bbb 100644 --- a/xcode/ios/DemoViewController.h +++ b/xcode/ios/DemoViewController.h @@ -13,6 +13,7 @@ /** The main view controller for the demo storyboard. */ @interface DemoViewController : UIViewController +-(void) shutdownExample; @end diff --git a/xcode/ios/DemoViewController.mm b/xcode/ios/DemoViewController.mm index 2fa3d098..3e5e65d7 100644 --- a/xcode/ios/DemoViewController.mm +++ b/xcode/ios/DemoViewController.mm @@ -6,6 +6,7 @@ */ #import "DemoViewController.h" +#import "AppDelegate.h" #include "MVKExample.h" @@ -22,6 +23,7 @@ const std::string getAssetPath() { MVKExample* _mvkExample; CADisplayLink* _displayLink; BOOL _viewHasAppeared; + CGPoint _startPoint; } /** Since this is a single-view app, init Vulkan when the view is loaded. */ @@ -31,26 +33,37 @@ const std::string getAssetPath() { self.view.contentScaleFactor = UIScreen.mainScreen.nativeScale; _mvkExample = new MVKExample(self.view); - + + // SRS - Enable AppDelegate to call into DemoViewController for handling app lifecycle events (e.g. termination) + auto appDelegate = (AppDelegate *)UIApplication.sharedApplication.delegate; + appDelegate.viewController = self; + uint32_t fps = 60; _displayLink = [CADisplayLink displayLinkWithTarget: self selector: @selector(renderFrame)]; [_displayLink setFrameInterval: 60 / fps]; [_displayLink addToRunLoop: NSRunLoop.currentRunLoop forMode: NSDefaultRunLoopMode]; - // SRS - set VulkanExampleBase::refreshPeriod to calibrate the frame animation rate - _mvkExample->setRefreshPeriod( 1.0 / fps ); - // Setup double tap gesture to toggle virtual keyboard - UITapGestureRecognizer* tapSelector = [[UITapGestureRecognizer alloc] - initWithTarget: self action: @selector(handleTapGesture:)]; + UITapGestureRecognizer* tapSelector = [[[UITapGestureRecognizer alloc] + initWithTarget: self action: @selector(handleTapGesture:)] autorelease]; tapSelector.numberOfTapsRequired = 2; tapSelector.cancelsTouchesInView = YES; + tapSelector.requiresExclusiveTouchType = YES; [self.view addGestureRecognizer: tapSelector]; + // SRS - Setup pan gesture to detect and activate translation + UIPanGestureRecognizer* panSelector = [[[UIPanGestureRecognizer alloc] + initWithTarget: self action: @selector(handlePanGesture:)] autorelease]; + panSelector.minimumNumberOfTouches = 2; + panSelector.cancelsTouchesInView = YES; + panSelector.requiresExclusiveTouchType = YES; + [self.view addGestureRecognizer: panSelector]; + // SRS - Setup pinch gesture to detect and activate zoom - UIPinchGestureRecognizer* pinchSelector = [[UIPinchGestureRecognizer alloc] - initWithTarget: self action: @selector(handlePinchGesture:)]; + UIPinchGestureRecognizer* pinchSelector = [[[UIPinchGestureRecognizer alloc] + initWithTarget: self action: @selector(handlePinchGesture:)] autorelease]; pinchSelector.cancelsTouchesInView = YES; + pinchSelector.requiresExclusiveTouchType = YES; [self.view addGestureRecognizer: pinchSelector]; _viewHasAppeared = NO; @@ -68,9 +81,9 @@ const std::string getAssetPath() { _mvkExample->displayLinkOutputCb(); // SRS - Call displayLinkOutputCb() to animate frames vs. renderFrame() for static image } --(void) dealloc { - delete _mvkExample; - [super dealloc]; +-(void) shutdownExample { + [_displayLink invalidate]; + delete _mvkExample; } // Toggle the display of the virtual keyboard @@ -109,58 +122,84 @@ const std::string getAssetPath() { #pragma mark UITouch methods -// SRS - Handle touch events -(CGPoint) getTouchLocalPoint:(UIEvent*) theEvent { UITouch *touch = [[theEvent allTouches] anyObject]; - CGPoint point = [touch locationInView:self.view]; - point.x = point.x * self.view.contentScaleFactor; - point.y = point.y * self.view.contentScaleFactor; + CGPoint point = [touch locationInView: self.view]; + point.x *= self.view.contentScaleFactor; + point.y *= self.view.contentScaleFactor; return point; } +// SRS - Handle touch events -(void) touchesBegan:(NSSet*) touches withEvent:(UIEvent*) theEvent { - auto point = [self getTouchLocalPoint:theEvent]; if (touches.count == 1) { - // Single touch for imgui select and camera rotation + auto point = [self getTouchLocalPoint: theEvent]; _mvkExample->mouseDown(point.x, point.y); } - else { - // Multi-touch for swipe translation (note: pinch gesture will cancel/override) - _mvkExample->otherMouseDown(point.x, point.y); - } } -(void) touchesMoved:(NSSet*) touches withEvent:(UIEvent*) theEvent { - auto point = [self getTouchLocalPoint:theEvent]; - _mvkExample->mouseDragged(point.x, point.y); + if (touches.count == 1) { + auto point = [self getTouchLocalPoint: theEvent]; + _mvkExample->mouseDragged(point.x, point.y); + } } -(void) touchesEnded:(NSSet*) touches withEvent:(UIEvent*) theEvent { _mvkExample->mouseUp(); - _mvkExample->otherMouseUp(); } -(void) touchesCancelled:(NSSet*) touches withEvent:(UIEvent*) theEvent { _mvkExample->mouseUp(); - _mvkExample->otherMouseUp(); +} + +#pragma mark UIGesture methods + +-(CGPoint) getGestureLocalPoint:(UIGestureRecognizer*) gestureRecognizer { + CGPoint point = [gestureRecognizer locationInView: self.view]; + point.x *= self.view.contentScaleFactor; + point.y *= self.view.contentScaleFactor; + return point; +} + +// SRS - Respond to pan gestures for translation +-(void) handlePanGesture: (UIPanGestureRecognizer*) gestureRecognizer { + switch (gestureRecognizer.state) { + case UIGestureRecognizerStateBegan: { + _startPoint = [self getGestureLocalPoint: gestureRecognizer]; + _mvkExample->otherMouseDown(_startPoint.x, _startPoint.y); + break; + } + case UIGestureRecognizerStateChanged: { + auto translation = [gestureRecognizer translationInView: self.view]; + translation.x *= self.view.contentScaleFactor; + translation.y *= self.view.contentScaleFactor; + _mvkExample->mouseDragged(_startPoint.x + translation.x, _startPoint.y + translation.y); + break; + } + default: { + _mvkExample->otherMouseUp(); + break; + } + } } // SRS - Respond to pinch gestures for zoom -(void) handlePinchGesture: (UIPinchGestureRecognizer*) gestureRecognizer { - if (gestureRecognizer.state == UIGestureRecognizerStateBegan) { - auto point = [gestureRecognizer locationInView:self.view]; - point.x = point.x * self.view.contentScaleFactor; - point.y = point.y * self.view.contentScaleFactor; - _mvkExample->rightMouseDown(point.x, point.y); - } - else if (gestureRecognizer.state == UIGestureRecognizerStateChanged) { - auto point = [gestureRecognizer locationInView:self.view]; - point.x = point.x * self.view.contentScaleFactor; - point.y = point.y * self.view.contentScaleFactor; - _mvkExample->mouseDragged(point.x, point.y - gestureRecognizer.view.frame.size.height / 2.0 * log(gestureRecognizer.scale)); - } - else if (gestureRecognizer.state == UIGestureRecognizerStateEnded) { - _mvkExample->rightMouseUp(); + switch (gestureRecognizer.state) { + case UIGestureRecognizerStateBegan: { + _startPoint = [self getGestureLocalPoint: gestureRecognizer]; + _mvkExample->rightMouseDown(_startPoint.x, _startPoint.y); + break; + } + case UIGestureRecognizerStateChanged: { + _mvkExample->mouseDragged(_startPoint.x, _startPoint.y - self.view.frame.size.height * log(gestureRecognizer.scale)); + break; + } + default: { + _mvkExample->rightMouseUp(); + break; + } } } diff --git a/xcode/macos/AppDelegate.h b/xcode/macos/AppDelegate.h index 3eb638e9..852413ce 100644 --- a/xcode/macos/AppDelegate.h +++ b/xcode/macos/AppDelegate.h @@ -9,4 +9,6 @@ @interface AppDelegate : NSObject +@property (strong, nonatomic) NSViewController *viewController; + @end diff --git a/xcode/macos/AppDelegate.m b/xcode/macos/AppDelegate.m index c3ce3b24..2a97e646 100644 --- a/xcode/macos/AppDelegate.m +++ b/xcode/macos/AppDelegate.m @@ -6,6 +6,7 @@ */ #import "AppDelegate.h" +#import "DemoViewController.h" @interface AppDelegate () @@ -19,6 +20,7 @@ - (void)applicationWillTerminate:(NSNotification *)aNotification { // Insert code here to tear down your application + [(DemoViewController *)_viewController shutdownExample]; } - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender { diff --git a/xcode/macos/DemoViewController.h b/xcode/macos/DemoViewController.h index 3cbedc48..c6337cfb 100644 --- a/xcode/macos/DemoViewController.h +++ b/xcode/macos/DemoViewController.h @@ -13,6 +13,7 @@ /** The main view controller for the demo storyboard. */ @interface DemoViewController : NSViewController +-(void) shutdownExample; @end diff --git a/xcode/macos/DemoViewController.mm b/xcode/macos/DemoViewController.mm index 333e0fe0..53d9e21c 100644 --- a/xcode/macos/DemoViewController.mm +++ b/xcode/macos/DemoViewController.mm @@ -6,6 +6,7 @@ */ #import "DemoViewController.h" +#import "AppDelegate.h" #import #include "MVKExample.h" @@ -43,25 +44,19 @@ MVKExample* _mvkExample; _mvkExample = new MVKExample(self.view); + // SRS - Enable AppDelegate to call into DemoViewController for handling application lifecycle events (e.g. termination) + auto appDelegate = (AppDelegate *)NSApplication.sharedApplication.delegate; + appDelegate.viewController = self; + CVDisplayLinkCreateWithActiveCGDisplays(&_displayLink); CVDisplayLinkSetOutputCallback(_displayLink, &DisplayLinkCallback, _mvkExample); CVDisplayLinkStart(_displayLink); } -// SRS - Center the window and set VulkanExampleBase::refreshPeriod from the active displayLink --(void) viewWillAppear { - [super viewWillAppear]; - - NSWindow* window = self.view.window; - [window center]; - - _mvkExample->setRefreshPeriod(CVDisplayLinkGetActualOutputVideoRefreshPeriod(_displayLink)); -} - --(void) dealloc { +-(void) shutdownExample { + CVDisplayLinkStop(_displayLink); CVDisplayLinkRelease(_displayLink); delete _mvkExample; - [super dealloc]; } @end @@ -86,6 +81,15 @@ MVKExample* _mvkExample; return layer; } +// SRS - Activate mouse cursor tracking within the view, set view as window delegate, and center the window +- (void) viewDidMoveToWindow { + auto trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds] options: (NSTrackingMouseMoved | NSTrackingActiveAlways | NSTrackingInVisibleRect) owner:self userInfo:nil]; + [self addTrackingArea: trackingArea]; + + [self.window setDelegate: self.window.contentView]; + [self.window center]; +} + -(BOOL) acceptsFirstResponder { return YES; } // SRS - Handle keyboard events @@ -151,9 +155,24 @@ MVKExample* _mvkExample; _mvkExample->mouseDragged(point.x, point.y); } +-(void) mouseMoved:(NSEvent*) theEvent { + auto point = [self getMouseLocalPoint:theEvent]; + _mvkExample->mouseDragged(point.x, point.y); +} + -(void) scrollWheel:(NSEvent*) theEvent { short wheelDelta = [theEvent deltaY]; _mvkExample->scrollWheel(wheelDelta); } +- (void)windowWillEnterFullScreen:(NSNotification *)notification +{ + _mvkExample->fullScreen(true); +} + +- (void)windowWillExitFullScreen:(NSNotification *)notification +{ + _mvkExample->fullScreen(false); +} + @end From 121612857ca34c7f21894b6b0cfe8ab2546a8210 Mon Sep 17 00:00:00 2001 From: Stephen Saunders Date: Wed, 1 Jun 2022 13:02:33 -0400 Subject: [PATCH 15/36] Fixes in examples: support swapchain image count change on resize, fix multiple validation layer errors on resize and quit, multiview now supports resize/fullscreen, computecloth deltaT now based on frame time, multisampling recreates attachments on resize, P key now pauses computeparticles, descriptorsets, and pushdescriptors --- examples/computecloth/computecloth.cpp | 7 ++- examples/computenbody/computenbody.cpp | 44 ++++++------- .../computeparticles/computeparticles.cpp | 46 +++++++------- examples/descriptorsets/descriptorsets.cpp | 6 +- .../inputattachments/inputattachments.cpp | 16 ++++- examples/multisampling/multisampling.cpp | 17 +++++ examples/multiview/multiview.cpp | 62 ++++++++++++++++--- examples/pushdescriptors/pushdescriptors.cpp | 6 +- examples/textoverlay/textoverlay.cpp | 6 +- examples/triangle/triangle.cpp | 3 + 10 files changed, 148 insertions(+), 65 deletions(-) diff --git a/examples/computecloth/computecloth.cpp b/examples/computecloth/computecloth.cpp index b08fd55c..d81567d7 100644 --- a/examples/computecloth/computecloth.cpp +++ b/examples/computecloth/computecloth.cpp @@ -101,6 +101,7 @@ public: ~VulkanExample() { // Graphics + graphics.indices.destroy(); graphics.uniformBuffer.destroy(); vkDestroyPipeline(device, graphics.pipelines.cloth, nullptr); vkDestroyPipeline(device, graphics.pipelines.sphere, nullptr); @@ -670,13 +671,13 @@ public: void updateComputeUBO() { if (!paused) { - compute.ubo.deltaT = 0.000005f; + //compute.ubo.deltaT = 0.000005f; // todo: base on frametime - //compute.ubo.deltaT = frameTimer * 0.0075f; + compute.ubo.deltaT = frameTimer * 0.0015f; if (simulateWind) { std::default_random_engine rndEngine(benchmark.active ? 0 : (unsigned)time(nullptr)); - std::uniform_real_distribution rd(1.0f, 6.0f); + std::uniform_real_distribution rd(1.0f, 30.0f); compute.ubo.gravity.x = cos(glm::radians(-timer * 360.0f)) * (rd(rndEngine) - rd(rndEngine)); compute.ubo.gravity.z = sin(glm::radians(timer * 360.0f)) * (rd(rndEngine) - rd(rndEngine)); } diff --git a/examples/computenbody/computenbody.cpp b/examples/computenbody/computenbody.cpp index 0d9b2a32..9dd01594 100644 --- a/examples/computenbody/computenbody.cpp +++ b/examples/computenbody/computenbody.cpp @@ -620,6 +620,13 @@ public: // Semaphore for compute & graphics sync VkSemaphoreCreateInfo semaphoreCreateInfo = vks::initializers::semaphoreCreateInfo(); VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &graphics.semaphore)); + + // Signal the semaphore + VkSubmitInfo submitInfo = vks::initializers::submitInfo(); + submitInfo.signalSemaphoreCount = 1; + submitInfo.pSignalSemaphores = &graphics.semaphore; + VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); + VK_CHECK_RESULT(vkQueueWaitIdle(queue)); } void prepareCompute() @@ -736,13 +743,6 @@ public: VkSemaphoreCreateInfo semaphoreCreateInfo = vks::initializers::semaphoreCreateInfo(); VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &compute.semaphore)); - // Signal the semaphore - VkSubmitInfo submitInfo = vks::initializers::submitInfo(); - submitInfo.signalSemaphoreCount = 1; - submitInfo.pSignalSemaphores = &compute.semaphore; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VK_CHECK_RESULT(vkQueueWaitIdle(queue)); - // Build a single command buffer containing the compute dispatch commands buildComputeCommandBuffer(); @@ -841,6 +841,20 @@ public: void draw() { + // Wait for rendering finished + VkPipelineStageFlags waitStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; + + // Submit compute commands + VkSubmitInfo computeSubmitInfo = vks::initializers::submitInfo(); + computeSubmitInfo.commandBufferCount = 1; + computeSubmitInfo.pCommandBuffers = &compute.commandBuffer; + computeSubmitInfo.waitSemaphoreCount = 1; + computeSubmitInfo.pWaitSemaphores = &graphics.semaphore; + computeSubmitInfo.pWaitDstStageMask = &waitStageMask; + computeSubmitInfo.signalSemaphoreCount = 1; + computeSubmitInfo.pSignalSemaphores = &compute.semaphore; + VK_CHECK_RESULT(vkQueueSubmit(compute.queue, 1, &computeSubmitInfo, VK_NULL_HANDLE)); + VulkanExampleBase::prepareFrame(); VkPipelineStageFlags graphicsWaitStageMasks[] = { VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; @@ -858,20 +872,6 @@ public: VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); VulkanExampleBase::submitFrame(); - - // Wait for rendering finished - VkPipelineStageFlags waitStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; - - // Submit compute commands - VkSubmitInfo computeSubmitInfo = vks::initializers::submitInfo(); - computeSubmitInfo.commandBufferCount = 1; - computeSubmitInfo.pCommandBuffers = &compute.commandBuffer; - computeSubmitInfo.waitSemaphoreCount = 1; - computeSubmitInfo.pWaitSemaphores = &graphics.semaphore; - computeSubmitInfo.pWaitDstStageMask = &waitStageMask; - computeSubmitInfo.signalSemaphoreCount = 1; - computeSubmitInfo.pSignalSemaphores = &compute.semaphore; - VK_CHECK_RESULT(vkQueueSubmit(compute.queue, 1, &computeSubmitInfo, VK_NULL_HANDLE)); } void prepare() @@ -901,4 +901,4 @@ public: } }; -VULKAN_EXAMPLE_MAIN() \ No newline at end of file +VULKAN_EXAMPLE_MAIN() diff --git a/examples/computeparticles/computeparticles.cpp b/examples/computeparticles/computeparticles.cpp index 48bfe07e..7c5b79c8 100644 --- a/examples/computeparticles/computeparticles.cpp +++ b/examples/computeparticles/computeparticles.cpp @@ -86,6 +86,7 @@ public: vkDestroyPipeline(device, graphics.pipeline, nullptr); vkDestroyPipelineLayout(device, graphics.pipelineLayout, nullptr); vkDestroyDescriptorSetLayout(device, graphics.descriptorSetLayout, nullptr); + vkDestroySemaphore(device, graphics.semaphore, nullptr); // Compute compute.storageBuffer.destroy(); @@ -551,6 +552,13 @@ public: // Semaphore for compute & graphics sync VkSemaphoreCreateInfo semaphoreCreateInfo = vks::initializers::semaphoreCreateInfo(); VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &graphics.semaphore)); + + // Signal the semaphore + VkSubmitInfo submitInfo = vks::initializers::submitInfo(); + submitInfo.signalSemaphoreCount = 1; + submitInfo.pSignalSemaphores = &graphics.semaphore; + VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); + VK_CHECK_RESULT(vkQueueWaitIdle(queue)); } void prepareCompute() @@ -636,13 +644,6 @@ public: VkSemaphoreCreateInfo semaphoreCreateInfo = vks::initializers::semaphoreCreateInfo(); VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &compute.semaphore)); - // Signal the semaphore - VkSubmitInfo submitInfo = vks::initializers::submitInfo(); - submitInfo.signalSemaphoreCount = 1; - submitInfo.pSignalSemaphores = &compute.semaphore; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - VK_CHECK_RESULT(vkQueueWaitIdle(queue)); - // Build a single command buffer containing the compute dispatch commands buildComputeCommandBuffer(); @@ -716,7 +717,7 @@ public: void updateUniformBuffers() { - compute.ubo.deltaT = frameTimer * 2.5f; + compute.ubo.deltaT = paused ? 0.0f : frameTimer * 2.5f; if (!attachToCursor) { compute.ubo.destX = sin(glm::radians(timer * 360.0f)) * 0.75f; @@ -735,6 +736,20 @@ public: void draw() { + // Wait for rendering finished + VkPipelineStageFlags waitStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; + + // Submit compute commands + VkSubmitInfo computeSubmitInfo = vks::initializers::submitInfo(); + computeSubmitInfo.commandBufferCount = 1; + computeSubmitInfo.pCommandBuffers = &compute.commandBuffer; + computeSubmitInfo.waitSemaphoreCount = 1; + computeSubmitInfo.pWaitSemaphores = &graphics.semaphore; + computeSubmitInfo.pWaitDstStageMask = &waitStageMask; + computeSubmitInfo.signalSemaphoreCount = 1; + computeSubmitInfo.pSignalSemaphores = &compute.semaphore; + VK_CHECK_RESULT(vkQueueSubmit(compute.queue, 1, &computeSubmitInfo, VK_NULL_HANDLE)); + VulkanExampleBase::prepareFrame(); VkPipelineStageFlags graphicsWaitStageMasks[] = { VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; @@ -752,21 +767,6 @@ public: VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); VulkanExampleBase::submitFrame(); - - // Wait for rendering finished - VkPipelineStageFlags waitStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; - - // Submit compute commands - VkSubmitInfo computeSubmitInfo = vks::initializers::submitInfo(); - computeSubmitInfo.commandBufferCount = 1; - computeSubmitInfo.pCommandBuffers = &compute.commandBuffer; - computeSubmitInfo.waitSemaphoreCount = 1; - computeSubmitInfo.pWaitSemaphores = &graphics.semaphore; - computeSubmitInfo.pWaitDstStageMask = &waitStageMask; - computeSubmitInfo.signalSemaphoreCount = 1; - computeSubmitInfo.pSignalSemaphores = &compute.semaphore; - VK_CHECK_RESULT(vkQueueSubmit(compute.queue, 1, &computeSubmitInfo, VK_NULL_HANDLE)); - } void prepare() diff --git a/examples/descriptorsets/descriptorsets.cpp b/examples/descriptorsets/descriptorsets.cpp index 5afbf6aa..b3955c82 100644 --- a/examples/descriptorsets/descriptorsets.cpp +++ b/examples/descriptorsets/descriptorsets.cpp @@ -362,7 +362,7 @@ public: if (!prepared) return; draw(); - if (animate) { + if (animate && !paused) { cubes[0].rotation.x += 2.5f * frameTimer; if (cubes[0].rotation.x > 360.0f) cubes[0].rotation.x -= 360.0f; @@ -370,7 +370,7 @@ public: if (cubes[1].rotation.x > 360.0f) cubes[1].rotation.x -= 360.0f; } - if ((camera.updated) || (animate)) { + if ((camera.updated) || (animate && !paused)) { updateUniformBuffers(); } } @@ -383,4 +383,4 @@ public: } }; -VULKAN_EXAMPLE_MAIN() \ No newline at end of file +VULKAN_EXAMPLE_MAIN() diff --git a/examples/inputattachments/inputattachments.cpp b/examples/inputattachments/inputattachments.cpp index 4b454b08..f0927815 100644 --- a/examples/inputattachments/inputattachments.cpp +++ b/examples/inputattachments/inputattachments.cpp @@ -180,11 +180,23 @@ public: for (auto i = 0; i < attachments.size(); i++) { clearAttachment(&attachments[i].color); clearAttachment(&attachments[i].depth); + } + + // SRS - Recreate attachments and descriptors in case number of swapchain images has changed on resize + attachments.resize(swapChain.imageCount); + for (auto i = 0; i < attachments.size(); i++) { createAttachment(colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, &attachments[i].color); createAttachment(depthFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, &attachments[i].depth); - // Since the framebuffers/attachments are referred in the descriptor sets, these need to be updated too - updateAttachmentReadDescriptors(i); } + + vkDestroyPipelineLayout(device, pipelineLayouts.attachmentWrite, nullptr); + vkDestroyPipelineLayout(device, pipelineLayouts.attachmentRead, nullptr); + vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.attachmentWrite, nullptr); + vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.attachmentRead, nullptr); + vkDestroyDescriptorPool(device, descriptorPool, nullptr); + + // Since the framebuffers/attachments are referred in the descriptor sets, these need to be updated on resize + setupDescriptors(); } VkImageView views[3]; diff --git a/examples/multisampling/multisampling.cpp b/examples/multisampling/multisampling.cpp index 408e18f7..f73cef79 100644 --- a/examples/multisampling/multisampling.cpp +++ b/examples/multisampling/multisampling.cpp @@ -48,6 +48,7 @@ public: VkPipelineLayout pipelineLayout; VkDescriptorSet descriptorSet; VkDescriptorSetLayout descriptorSetLayout; + VkExtent2D attachmentSize; VulkanExample() : VulkanExampleBase(ENABLE_VALIDATION) { @@ -199,6 +200,8 @@ public: void setupRenderPass() { // Overrides the virtual function of the base class + + attachmentSize = { width, height }; std::array attachments = {}; @@ -290,6 +293,20 @@ public: { // Overrides the virtual function of the base class + // SRS - If the window is resized, the MSAA attachments need to be released and recreated + if (attachmentSize.width != width || attachmentSize.height != height) + { + attachmentSize = { width, height }; + + // Destroy MSAA target + vkDestroyImage(device, multisampleTarget.color.image, nullptr); + vkDestroyImageView(device, multisampleTarget.color.view, nullptr); + vkFreeMemory(device, multisampleTarget.color.memory, nullptr); + vkDestroyImage(device, multisampleTarget.depth.image, nullptr); + vkDestroyImageView(device, multisampleTarget.depth.view, nullptr); + vkFreeMemory(device, multisampleTarget.depth.memory, nullptr); + } + std::array attachments; setupMultisampleTarget(); diff --git a/examples/multiview/multiview.cpp b/examples/multiview/multiview.cpp index a73992f3..17a4a676 100644 --- a/examples/multiview/multiview.cpp +++ b/examples/multiview/multiview.cpp @@ -98,6 +98,7 @@ public: vkDestroySampler(device, multiviewPass.sampler, nullptr); vkDestroyFramebuffer(device, multiviewPass.frameBuffer, nullptr); + vkFreeCommandBuffers(device, cmdPool, static_cast(multiviewPass.commandBuffers.size()), multiviewPass.commandBuffers.data()); vkDestroySemaphore(device, multiviewPass.semaphore, nullptr); for (auto& fence : multiviewPass.waitFences) { vkDestroyFence(device, fence, nullptr); @@ -337,6 +338,9 @@ public: void buildCommandBuffers() { + if (resized) + return; + /* View display */ @@ -392,11 +396,6 @@ public: Multiview layered attachment scene rendering */ - multiviewPass.commandBuffers.resize(drawCmdBuffers.size()); - - VkCommandBufferAllocateInfo cmdBufAllocateInfo = vks::initializers::commandBufferAllocateInfo(cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, static_cast(drawCmdBuffers.size())); - VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, multiviewPass.commandBuffers.data())); - { VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); @@ -467,13 +466,18 @@ public: */ VkDescriptorSetAllocateInfo allocateInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocateInfo, &descriptorSet)); + updateDescriptors(); + } + + void updateDescriptors() + { std::vector writeDescriptorSets = { vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor), vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &multiviewPass.descriptor), }; vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); } - + void preparePipelines() { @@ -669,6 +673,11 @@ public: prepareUniformBuffers(); prepareDescriptors(); preparePipelines(); + + VkCommandBufferAllocateInfo cmdBufAllocateInfo = vks::initializers::commandBufferAllocateInfo(cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, static_cast(drawCmdBuffers.size())); + multiviewPass.commandBuffers.resize(drawCmdBuffers.size()); + VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, multiviewPass.commandBuffers.data())); + buildCommandBuffers(); VkFenceCreateInfo fenceCreateInfo = vks::initializers::fenceCreateInfo(VK_FENCE_CREATE_SIGNALED_BIT); @@ -680,6 +689,45 @@ public: prepared = true; } + // SRS - Recreate and update Multiview resources when window size has changed + virtual void windowResized() + { + vkDestroyImageView(device, multiviewPass.color.view, nullptr); + vkDestroyImage(device, multiviewPass.color.image, nullptr); + vkFreeMemory(device, multiviewPass.color.memory, nullptr); + vkDestroyImageView(device, multiviewPass.depth.view, nullptr); + vkDestroyImage(device, multiviewPass.depth.image, nullptr); + vkFreeMemory(device, multiviewPass.depth.memory, nullptr); + + vkDestroyRenderPass(device, multiviewPass.renderPass, nullptr); + vkDestroySampler(device, multiviewPass.sampler, nullptr); + vkDestroyFramebuffer(device, multiviewPass.frameBuffer, nullptr); + + prepareMultiview(); + updateDescriptors(); + + // SRS - Recreate Multiview command buffers in case number of swapchain images has changed on resize + vkFreeCommandBuffers(device, cmdPool, static_cast(multiviewPass.commandBuffers.size()), multiviewPass.commandBuffers.data()); + + VkCommandBufferAllocateInfo cmdBufAllocateInfo = vks::initializers::commandBufferAllocateInfo(cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, static_cast(drawCmdBuffers.size())); + multiviewPass.commandBuffers.resize(drawCmdBuffers.size()); + VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, multiviewPass.commandBuffers.data())); + + resized = false; + buildCommandBuffers(); + + // SRS - Recreate Multiview fences in case number of swapchain images has changed on resize + for (auto& fence : multiviewPass.waitFences) { + vkDestroyFence(device, fence, nullptr); + } + + VkFenceCreateInfo fenceCreateInfo = vks::initializers::fenceCreateInfo(VK_FENCE_CREATE_SIGNALED_BIT); + multiviewPass.waitFences.resize(multiviewPass.commandBuffers.size()); + for (auto& fence : multiviewPass.waitFences) { + VK_CHECK_RESULT(vkCreateFence(device, &fenceCreateInfo, nullptr, &fence)); + } + } + virtual void render() { if (!prepared) @@ -704,4 +752,4 @@ public: }; -VULKAN_EXAMPLE_MAIN() \ No newline at end of file +VULKAN_EXAMPLE_MAIN() diff --git a/examples/pushdescriptors/pushdescriptors.cpp b/examples/pushdescriptors/pushdescriptors.cpp index 080f5b41..b1979828 100644 --- a/examples/pushdescriptors/pushdescriptors.cpp +++ b/examples/pushdescriptors/pushdescriptors.cpp @@ -262,7 +262,7 @@ public: memcpy(cube.uniformBuffer.mapped, &cube.modelMat, sizeof(glm::mat4)); } - if (animate) { + if (animate && !paused) { cubes[0].rotation.x += 2.5f * frameTimer; if (cubes[0].rotation.x > 360.0f) cubes[0].rotation.x -= 360.0f; @@ -323,7 +323,7 @@ public: if (!prepared) return; draw(); - if (animate) { + if (animate && !paused) { cubes[0].rotation.x += 2.5f * frameTimer; if (cubes[0].rotation.x > 360.0f) cubes[0].rotation.x -= 360.0f; @@ -348,4 +348,4 @@ public: } }; -VULKAN_EXAMPLE_MAIN() \ No newline at end of file +VULKAN_EXAMPLE_MAIN() diff --git a/examples/textoverlay/textoverlay.cpp b/examples/textoverlay/textoverlay.cpp index 85b70727..7672b2b8 100644 --- a/examples/textoverlay/textoverlay.cpp +++ b/examples/textoverlay/textoverlay.cpp @@ -901,7 +901,9 @@ public: virtual void windowResized() { - updateTextOverlay(); + // SRS - Recreate text overlay resources in case number of swapchain images has changed on resize + delete textOverlay; + prepareTextOverlay(); } #if !defined(__ANDROID__) @@ -917,4 +919,4 @@ public: #endif }; -VULKAN_EXAMPLE_MAIN() \ No newline at end of file +VULKAN_EXAMPLE_MAIN() diff --git a/examples/triangle/triangle.cpp b/examples/triangle/triangle.cpp index 4a6336f7..6b16b296 100644 --- a/examples/triangle/triangle.cpp +++ b/examples/triangle/triangle.cpp @@ -126,6 +126,9 @@ public: ~VulkanExample() { + // SRS - Ensure all operations on the device have finished before destroying resources + vkDeviceWaitIdle(device); + // Clean up used Vulkan resources // Note: Inherited destructor cleans up resources stored in base class vkDestroyPipeline(device, pipeline, nullptr); From 17aaa7305b283e3cb102ff539513fb5cc13d7d49 Mon Sep 17 00:00:00 2001 From: Stephen Saunders Date: Sat, 11 Jun 2022 20:14:55 -0400 Subject: [PATCH 16/36] Revert to original tDiff calculation, make frame-based tDiff calculation specific to iOS/macOS xcode examples project --- base/vulkanexamplebase.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/base/vulkanexamplebase.cpp b/base/vulkanexamplebase.cpp index b25dc05c..01c66c40 100644 --- a/base/vulkanexamplebase.cpp +++ b/base/vulkanexamplebase.cpp @@ -255,7 +255,7 @@ VkPipelineShaderStageCreateInfo VulkanExampleBase::loadShader(std::string fileNa void VulkanExampleBase::nextFrame() { - //auto tStart = std::chrono::high_resolution_clock::now(); + auto tStart = std::chrono::high_resolution_clock::now(); if (viewUpdated) { viewUpdated = false; @@ -265,9 +265,12 @@ void VulkanExampleBase::nextFrame() render(); frameCounter++; auto tEnd = std::chrono::high_resolution_clock::now(); - // SRS - Calculate tDiff as time between frames vs. rendering time for Win32/macOS/iOS vsync portability - //auto tDiff = std::chrono::duration(tEnd - tStart).count(); +#if (defined(VK_USE_PLATFORM_IOS_MVK) || (defined(VK_USE_PLATFORM_MACOS_MVK) && !defined(VK_EXAMPLE_XCODE_GENERATED))) + // SRS - Calculate tDiff as time between frames vs. rendering time for iOS/macOS displayLink-driven examples project auto tDiff = std::chrono::duration(tEnd - tPrevEnd).count(); +#else + auto tDiff = std::chrono::duration(tEnd - tStart).count(); +#endif frameTimer = (float)tDiff / 1000.0f; camera.update(frameTimer); if (camera.moving()) @@ -740,6 +743,7 @@ void VulkanExampleBase::prepareFrame() if (result == VK_ERROR_OUT_OF_DATE_KHR) { windowResize(); } + return; } else { VK_CHECK_RESULT(result); @@ -1750,7 +1754,7 @@ static CVReturn displayLinkOutputCallback(CVDisplayLinkRef displayLink, const CV } // SRS - Window resizing already handled by windowResize() in VulkanExampleBase::submitFrame() -// - handling window resize events here is redundant and can cause interaction problems +// - handling window resize events here is redundant and can cause thread interaction problems /* - (NSSize)windowWillResize:(NSWindow *)sender toSize:(NSSize)frameSize { From b2f501dc98c967ec5f49d2e47d4f4975753b2a48 Mon Sep 17 00:00:00 2001 From: Stephen Saunders Date: Mon, 13 Jun 2022 22:53:48 -0400 Subject: [PATCH 17/36] Fix queue family transfer operations between graphics <-> compute queues, generalize getQueueFamilyIndex() to support VkQueueFlags vs. VkQueueFlagBits, computecloth deltaT now based on frameTimer --- base/VulkanDevice.cpp | 15 +- base/VulkanDevice.h | 2 +- examples/computecloth/computecloth.cpp | 39 ++-- .../computecullandlod/computecullandlod.cpp | 171 ++++++++++++++---- examples/computenbody/computenbody.cpp | 18 +- .../computeparticles/computeparticles.cpp | 13 +- .../computeraytracing/computeraytracing.cpp | 128 +++++++++++-- 7 files changed, 306 insertions(+), 80 deletions(-) diff --git a/base/VulkanDevice.cpp b/base/VulkanDevice.cpp index 6835a3dd..9208be7b 100644 --- a/base/VulkanDevice.cpp +++ b/base/VulkanDevice.cpp @@ -120,6 +120,7 @@ namespace vks /** * Get the index of a queue family that supports the requested queue flags + * SRS - support VkQueueFlags parameter for requesting multiple flags vs. VkQueueFlagBits for a single flag only * * @param queueFlags Queue flags to find a queue family index for * @@ -127,15 +128,15 @@ namespace vks * * @throw Throws an exception if no queue family index could be found that supports the requested flags */ - uint32_t VulkanDevice::getQueueFamilyIndex(VkQueueFlagBits queueFlags) const + uint32_t VulkanDevice::getQueueFamilyIndex(VkQueueFlags queueFlags) const { // Dedicated queue for compute // Try to find a queue family index that supports compute but not graphics - if (queueFlags & VK_QUEUE_COMPUTE_BIT) + if ((queueFlags & VK_QUEUE_COMPUTE_BIT) == queueFlags) { for (uint32_t i = 0; i < static_cast(queueFamilyProperties.size()); i++) { - if ((queueFamilyProperties[i].queueFlags & queueFlags) && ((queueFamilyProperties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0)) + if ((queueFamilyProperties[i].queueFlags & VK_QUEUE_COMPUTE_BIT) && ((queueFamilyProperties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0)) { return i; } @@ -144,11 +145,11 @@ namespace vks // Dedicated queue for transfer // Try to find a queue family index that supports transfer but not graphics and compute - if (queueFlags & VK_QUEUE_TRANSFER_BIT) + if ((queueFlags & VK_QUEUE_TRANSFER_BIT) == queueFlags) { for (uint32_t i = 0; i < static_cast(queueFamilyProperties.size()); i++) { - if ((queueFamilyProperties[i].queueFlags & queueFlags) && ((queueFamilyProperties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0) && ((queueFamilyProperties[i].queueFlags & VK_QUEUE_COMPUTE_BIT) == 0)) + if ((queueFamilyProperties[i].queueFlags & VK_QUEUE_TRANSFER_BIT) && ((queueFamilyProperties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0) && ((queueFamilyProperties[i].queueFlags & VK_QUEUE_COMPUTE_BIT) == 0)) { return i; } @@ -158,7 +159,7 @@ namespace vks // For other queue types or if no separate compute queue is present, return the first one to support the requested flags for (uint32_t i = 0; i < static_cast(queueFamilyProperties.size()); i++) { - if (queueFamilyProperties[i].queueFlags & queueFlags) + if ((queueFamilyProperties[i].queueFlags & queueFlags) == queueFlags) { return i; } @@ -233,7 +234,7 @@ namespace vks queueFamilyIndices.transfer = getQueueFamilyIndex(VK_QUEUE_TRANSFER_BIT); if ((queueFamilyIndices.transfer != queueFamilyIndices.graphics) && (queueFamilyIndices.transfer != queueFamilyIndices.compute)) { - // If compute family index differs, we need an additional queue create info for the compute queue + // If transfer family index differs, we need an additional queue create info for the transfer queue VkDeviceQueueCreateInfo queueInfo{}; queueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; queueInfo.queueFamilyIndex = queueFamilyIndices.transfer; diff --git a/base/VulkanDevice.h b/base/VulkanDevice.h index 0bb49879..fc41506a 100644 --- a/base/VulkanDevice.h +++ b/base/VulkanDevice.h @@ -55,7 +55,7 @@ struct VulkanDevice explicit VulkanDevice(VkPhysicalDevice physicalDevice); ~VulkanDevice(); uint32_t getMemoryType(uint32_t typeBits, VkMemoryPropertyFlags properties, VkBool32 *memTypeFound = nullptr) const; - uint32_t getQueueFamilyIndex(VkQueueFlagBits queueFlags) const; + uint32_t getQueueFamilyIndex(VkQueueFlags queueFlags) const; VkResult createLogicalDevice(VkPhysicalDeviceFeatures enabledFeatures, std::vector enabledExtensions, void *pNextChain, bool useSwapChain = true, VkQueueFlags requestedQueueTypes = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT); VkResult createBuffer(VkBufferUsageFlags usageFlags, VkMemoryPropertyFlags memoryPropertyFlags, VkDeviceSize size, VkBuffer *buffer, VkDeviceMemory *memory, void *data = nullptr); VkResult createBuffer(VkBufferUsageFlags usageFlags, VkMemoryPropertyFlags memoryPropertyFlags, vks::Buffer *buffer, VkDeviceSize size, void *data = nullptr); diff --git a/examples/computecloth/computecloth.cpp b/examples/computecloth/computecloth.cpp index d81567d7..5d4ae92a 100644 --- a/examples/computecloth/computecloth.cpp +++ b/examples/computecloth/computecloth.cpp @@ -136,12 +136,12 @@ public: textureCloth.loadFromFile(getAssetPath() + "textures/vulkan_cloth_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); } - void addGraphicsToComputeBarriers(VkCommandBuffer commandBuffer) + void addGraphicsToComputeBarriers(VkCommandBuffer commandBuffer, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask) { if (specializedComputeQueue) { VkBufferMemoryBarrier bufferBarrier = vks::initializers::bufferMemoryBarrier(); - bufferBarrier.srcAccessMask = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; - bufferBarrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT; + bufferBarrier.srcAccessMask = srcAccessMask; + bufferBarrier.dstAccessMask = dstAccessMask; bufferBarrier.srcQueueFamilyIndex = vulkanDevice->queueFamilyIndices.graphics; bufferBarrier.dstQueueFamilyIndex = vulkanDevice->queueFamilyIndices.compute; bufferBarrier.size = VK_WHOLE_SIZE; @@ -152,8 +152,8 @@ public: bufferBarrier.buffer = compute.storageBuffers.output.buffer; bufferBarriers.push_back(bufferBarrier); vkCmdPipelineBarrier(commandBuffer, - VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + srcStageMask, + dstStageMask, VK_FLAGS_NONE, 0, nullptr, static_cast(bufferBarriers.size()), bufferBarriers.data(), @@ -166,8 +166,8 @@ public: VkBufferMemoryBarrier bufferBarrier = vks::initializers::bufferMemoryBarrier(); bufferBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; bufferBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - bufferBarrier.srcQueueFamilyIndex = vulkanDevice->queueFamilyIndices.compute; - bufferBarrier.dstQueueFamilyIndex = vulkanDevice->queueFamilyIndices.compute; + bufferBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + bufferBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; bufferBarrier.size = VK_WHOLE_SIZE; std::vector bufferBarriers; bufferBarrier.buffer = compute.storageBuffers.input.buffer; @@ -184,12 +184,12 @@ public: 0, nullptr); } - void addComputeToGraphicsBarriers(VkCommandBuffer commandBuffer) + void addComputeToGraphicsBarriers(VkCommandBuffer commandBuffer, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask) { if (specializedComputeQueue) { VkBufferMemoryBarrier bufferBarrier = vks::initializers::bufferMemoryBarrier(); - bufferBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; - bufferBarrier.dstAccessMask = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; + bufferBarrier.srcAccessMask = srcAccessMask; + bufferBarrier.dstAccessMask = dstAccessMask; bufferBarrier.srcQueueFamilyIndex = vulkanDevice->queueFamilyIndices.compute; bufferBarrier.dstQueueFamilyIndex = vulkanDevice->queueFamilyIndices.graphics; bufferBarrier.size = VK_WHOLE_SIZE; @@ -200,8 +200,8 @@ public: bufferBarriers.push_back(bufferBarrier); vkCmdPipelineBarrier( commandBuffer, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, + srcStageMask, + dstStageMask, VK_FLAGS_NONE, 0, nullptr, static_cast(bufferBarriers.size()), bufferBarriers.data(), @@ -234,7 +234,7 @@ public: VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); // Acquire storage buffers from compute queue - addComputeToGraphicsBarriers(drawCmdBuffers[i]); + addComputeToGraphicsBarriers(drawCmdBuffers[i], 0, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT); // Draw the particle system using the update vertex buffer @@ -267,7 +267,7 @@ public: vkCmdEndRenderPass(drawCmdBuffers[i]); // release the storage buffers to the compute queue - addGraphicsToComputeBarriers(drawCmdBuffers[i]); + addGraphicsToComputeBarriers(drawCmdBuffers[i], VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, 0, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT); VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); } @@ -285,7 +285,7 @@ public: VK_CHECK_RESULT(vkBeginCommandBuffer(compute.commandBuffers[i], &cmdBufInfo)); // Acquire the storage buffers from the graphics queue - addGraphicsToComputeBarriers(compute.commandBuffers[i]); + addGraphicsToComputeBarriers(compute.commandBuffers[i], 0, VK_ACCESS_SHADER_WRITE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); vkCmdBindPipeline(compute.commandBuffers[i], VK_PIPELINE_BIND_POINT_COMPUTE, compute.pipeline); @@ -313,7 +313,7 @@ public: } // release the storage buffers back to the graphics queue - addComputeToGraphicsBarriers(compute.commandBuffers[i]); + addComputeToGraphicsBarriers(compute.commandBuffers[i], VK_ACCESS_SHADER_WRITE_BIT, 0, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT); vkEndCommandBuffer(compute.commandBuffers[i]); } } @@ -396,7 +396,7 @@ public: // Add an initial release barrier to the graphics queue, // so that when the compute command buffer executes for the first time // it doesn't complain about a lack of a corresponding "release" to its "acquire" - addGraphicsToComputeBarriers(copyCmd); + addGraphicsToComputeBarriers(copyCmd, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, 0, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT); vulkanDevice->flushCommandBuffer(copyCmd, queue, true); stagingBuffer.destroy(); @@ -673,11 +673,12 @@ public: if (!paused) { //compute.ubo.deltaT = 0.000005f; // todo: base on frametime - compute.ubo.deltaT = frameTimer * 0.0015f; + // SRS - Clamp frameTimer to max 20ms refresh period (e.g. if blocked on resize), otherwise image breakup can occur + compute.ubo.deltaT = fmin(frameTimer, 0.02) * 0.0025f; if (simulateWind) { std::default_random_engine rndEngine(benchmark.active ? 0 : (unsigned)time(nullptr)); - std::uniform_real_distribution rd(1.0f, 30.0f); + std::uniform_real_distribution rd(1.0f, 12.0f); compute.ubo.gravity.x = cos(glm::radians(-timer * 360.0f)) * (rd(rndEngine) - rd(rndEngine)); compute.ubo.gravity.z = sin(glm::radians(timer * 360.0f)) * (rd(rndEngine) - rd(rndEngine)); } diff --git a/examples/computecullandlod/computecullandlod.cpp b/examples/computecullandlod/computecullandlod.cpp index c1888659..5b5296d5 100644 --- a/examples/computecullandlod/computecullandlod.cpp +++ b/examples/computecullandlod/computecullandlod.cpp @@ -149,6 +149,32 @@ public: VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); + // Acquire barrier + if (vulkanDevice->queueFamilyIndices.graphics != vulkanDevice->queueFamilyIndices.compute) + { + VkBufferMemoryBarrier buffer_barrier = + { + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, + nullptr, + 0, + VK_ACCESS_INDIRECT_COMMAND_READ_BIT, + vulkanDevice->queueFamilyIndices.compute, + vulkanDevice->queueFamilyIndices.graphics, + indirectCommandsBuffer.buffer, + 0, + indirectCommandsBuffer.descriptor.range + }; + + vkCmdPipelineBarrier( + drawCmdBuffers[i], + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, + 0, + 0, nullptr, + 1, &buffer_barrier, + 0, nullptr); + } + vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); @@ -169,7 +195,7 @@ public: if (vulkanDevice->features.multiDrawIndirect) { - vkCmdDrawIndexedIndirect(drawCmdBuffers[i], indirectCommandsBuffer.buffer, 0, indirectCommands.size(), sizeof(VkDrawIndexedIndirectCommand)); + vkCmdDrawIndexedIndirect(drawCmdBuffers[i], indirectCommandsBuffer.buffer, 0, static_cast(indirectCommands.size()), sizeof(VkDrawIndexedIndirectCommand)); } else { @@ -184,6 +210,32 @@ public: vkCmdEndRenderPass(drawCmdBuffers[i]); + // Release barrier + if (vulkanDevice->queueFamilyIndices.graphics != vulkanDevice->queueFamilyIndices.compute) + { + VkBufferMemoryBarrier buffer_barrier = + { + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, + nullptr, + VK_ACCESS_INDIRECT_COMMAND_READ_BIT, + 0, + vulkanDevice->queueFamilyIndices.graphics, + vulkanDevice->queueFamilyIndices.compute, + indirectCommandsBuffer.buffer, + 0, + indirectCommandsBuffer.descriptor.range + }; + + vkCmdPipelineBarrier( + drawCmdBuffers[i], + VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + 0, + 0, nullptr, + 1, &buffer_barrier, + 0, nullptr); + } + VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); } } @@ -200,23 +252,32 @@ public: VK_CHECK_RESULT(vkBeginCommandBuffer(compute.commandBuffer, &cmdBufInfo)); + // Acquire barrier // Add memory barrier to ensure that the indirect commands have been consumed before the compute shader updates them - VkBufferMemoryBarrier bufferBarrier = vks::initializers::bufferMemoryBarrier(); - bufferBarrier.buffer = indirectCommandsBuffer.buffer; - bufferBarrier.size = indirectCommandsBuffer.descriptor.range; - bufferBarrier.srcAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT; - bufferBarrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT; - bufferBarrier.srcQueueFamilyIndex = vulkanDevice->queueFamilyIndices.graphics; - bufferBarrier.dstQueueFamilyIndex = vulkanDevice->queueFamilyIndices.compute; + if (vulkanDevice->queueFamilyIndices.graphics != vulkanDevice->queueFamilyIndices.compute) + { + VkBufferMemoryBarrier buffer_barrier = + { + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, + nullptr, + 0, + VK_ACCESS_SHADER_WRITE_BIT, + vulkanDevice->queueFamilyIndices.graphics, + vulkanDevice->queueFamilyIndices.compute, + indirectCommandsBuffer.buffer, + 0, + indirectCommandsBuffer.descriptor.range + }; - vkCmdPipelineBarrier( - compute.commandBuffer, - VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - VK_FLAGS_NONE, - 0, nullptr, - 1, &bufferBarrier, - 0, nullptr); + vkCmdPipelineBarrier( + compute.commandBuffer, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_FLAGS_NONE, + 0, nullptr, + 1, &buffer_barrier, + 0, nullptr); + } vkCmdBindPipeline(compute.commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, compute.pipeline); vkCmdBindDescriptorSets(compute.commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, compute.pipelineLayout, 0, 1, &compute.descriptorSet, 0, 0); @@ -226,22 +287,32 @@ public: // It also determines the lod to use depending on distance to the viewer. vkCmdDispatch(compute.commandBuffer, objectCount / 16, 1, 1); + // Release barrier // Add memory barrier to ensure that the compute shader has finished writing the indirect command buffer before it's consumed - bufferBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; - bufferBarrier.dstAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT; - bufferBarrier.buffer = indirectCommandsBuffer.buffer; - bufferBarrier.size = indirectCommandsBuffer.descriptor.range; - bufferBarrier.srcQueueFamilyIndex = vulkanDevice->queueFamilyIndices.compute; - bufferBarrier.dstQueueFamilyIndex = vulkanDevice->queueFamilyIndices.graphics; + if (vulkanDevice->queueFamilyIndices.graphics != vulkanDevice->queueFamilyIndices.compute) + { + VkBufferMemoryBarrier buffer_barrier = + { + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, + nullptr, + VK_ACCESS_SHADER_WRITE_BIT, + 0, + vulkanDevice->queueFamilyIndices.compute, + vulkanDevice->queueFamilyIndices.graphics, + indirectCommandsBuffer.buffer, + 0, + indirectCommandsBuffer.descriptor.range + }; - vkCmdPipelineBarrier( - compute.commandBuffer, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, - VK_FLAGS_NONE, - 0, nullptr, - 1, &bufferBarrier, - 0, nullptr); + vkCmdPipelineBarrier( + compute.commandBuffer, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + VK_FLAGS_NONE, + 0, nullptr, + 1, &buffer_barrier, + 0, nullptr); + } // todo: barrier for indirect stats buffer? @@ -424,7 +495,38 @@ public: &instanceBuffer, stagingBuffer.size)); - vulkanDevice->copyBuffer(&stagingBuffer, &instanceBuffer, queue); + // Copy from staging buffer to instance buffer + VkCommandBuffer copyCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); + VkBufferCopy copyRegion = {}; + copyRegion.size = stagingBuffer.size; + vkCmdCopyBuffer(copyCmd, stagingBuffer.buffer, instanceBuffer.buffer, 1, ©Region); + // Add an initial release barrier to the graphics queue, + // so that when the compute command buffer executes for the first time + // it doesn't complain about a lack of a corresponding "release" to its "acquire" + if (vulkanDevice->queueFamilyIndices.graphics != vulkanDevice->queueFamilyIndices.compute) + { VkBufferMemoryBarrier buffer_barrier = + { + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, + nullptr, + VK_ACCESS_INDIRECT_COMMAND_READ_BIT, + 0, + vulkanDevice->queueFamilyIndices.graphics, + vulkanDevice->queueFamilyIndices.compute, + indirectCommandsBuffer.buffer, + 0, + indirectCommandsBuffer.descriptor.range + }; + + vkCmdPipelineBarrier( + copyCmd, + VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + 0, + 0, nullptr, + 1, &buffer_barrier, + 0, nullptr); + } + vulkanDevice->flushCommandBuffer(copyCmd, queue, true); stagingBuffer.destroy(); @@ -710,6 +812,11 @@ public: } } + virtual void viewChanged() + { + updateUniformBuffer(true); + } + virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) { if (overlay->header("Settings")) { @@ -726,4 +833,4 @@ public: } }; -VULKAN_EXAMPLE_MAIN() \ No newline at end of file +VULKAN_EXAMPLE_MAIN() diff --git a/examples/computenbody/computenbody.cpp b/examples/computenbody/computenbody.cpp index 9dd01594..dec0a00f 100644 --- a/examples/computenbody/computenbody.cpp +++ b/examples/computenbody/computenbody.cpp @@ -160,7 +160,7 @@ public: vkCmdPipelineBarrier( drawCmdBuffers[i], - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0, 0, nullptr, @@ -207,7 +207,7 @@ public: vkCmdPipelineBarrier( drawCmdBuffers[i], VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 1, &buffer_barrier, @@ -243,7 +243,7 @@ public: vkCmdPipelineBarrier( compute.commandBuffer, - VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, @@ -300,7 +300,7 @@ public: vkCmdPipelineBarrier( compute.commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 1, &buffer_barrier, @@ -417,7 +417,7 @@ public: vkCmdPipelineBarrier( copyCmd, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 1, &buffer_barrier, @@ -746,7 +746,9 @@ public: // Build a single command buffer containing the compute dispatch commands buildComputeCommandBuffer(); + // SRS - By reordering compute and graphics within draw(), the following code is no longer needed: // If graphics and compute queue family indices differ, acquire and immediately release the storage buffer, so that the initial acquire from the graphics command buffers are matched up properly + /* if (graphics.queueFamilyIndex != compute.queueFamilyIndex) { // Create a transient command buffer for setting up the initial buffer transfer state @@ -796,6 +798,7 @@ public: vulkanDevice->flushCommandBuffer(transferCmd, compute.queue, compute.commandPool); } + */ } // Prepare and initialize uniform buffer containing shader uniforms @@ -899,6 +902,11 @@ public: updateGraphicsUniformBuffers(); } } + + virtual void viewChanged() + { + updateGraphicsUniformBuffers(); + } }; VULKAN_EXAMPLE_MAIN() diff --git a/examples/computeparticles/computeparticles.cpp b/examples/computeparticles/computeparticles.cpp index 7c5b79c8..87f91a6d 100644 --- a/examples/computeparticles/computeparticles.cpp +++ b/examples/computeparticles/computeparticles.cpp @@ -149,7 +149,7 @@ public: vkCmdPipelineBarrier( drawCmdBuffers[i], - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0, 0, nullptr, @@ -196,7 +196,7 @@ public: vkCmdPipelineBarrier( drawCmdBuffers[i], VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 1, &buffer_barrier, @@ -234,7 +234,7 @@ public: vkCmdPipelineBarrier( compute.commandBuffer, - VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, @@ -267,7 +267,7 @@ public: vkCmdPipelineBarrier( compute.commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 1, &buffer_barrier, @@ -336,7 +336,7 @@ public: vkCmdPipelineBarrier( copyCmd, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 1, &buffer_barrier, @@ -647,7 +647,9 @@ public: // Build a single command buffer containing the compute dispatch commands buildComputeCommandBuffer(); + // SRS - By reordering compute and graphics within draw(), the following code is no longer needed: // If graphics and compute queue family indices differ, acquire and immediately release the storage buffer, so that the initial acquire from the graphics command buffers are matched up properly + /* if (graphics.queueFamilyIndex != compute.queueFamilyIndex) { // Create a transient command buffer for setting up the initial buffer transfer state @@ -697,6 +699,7 @@ public: vulkanDevice->flushCommandBuffer(transferCmd, compute.queue, compute.commandPool); } + */ } // Prepare and initialize uniform buffer containing shader uniforms diff --git a/examples/computeraytracing/computeraytracing.cpp b/examples/computeraytracing/computeraytracing.cpp index 6a9036c2..e857d1cd 100644 --- a/examples/computeraytracing/computeraytracing.cpp +++ b/examples/computeraytracing/computeraytracing.cpp @@ -94,6 +94,9 @@ public: ~VulkanExample() { + // SRS - Ensure all operations on the device have finished before destroying resources + vkDeviceWaitIdle(device); + // Graphics vkDestroyPipeline(device, graphics.pipeline, nullptr); vkDestroyPipelineLayout(device, graphics.pipelineLayout, nullptr); @@ -223,16 +226,38 @@ public: imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; imageMemoryBarrier.image = textureComputeTarget.image; imageMemoryBarrier.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; - imageMemoryBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; - imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - vkCmdPipelineBarrier( - drawCmdBuffers[i], - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - VK_FLAGS_NONE, - 0, nullptr, - 0, nullptr, - 1, &imageMemoryBarrier); + if (vulkanDevice->queueFamilyIndices.graphics != vulkanDevice->queueFamilyIndices.compute) + { + // Acquire barrier for graphics queue + imageMemoryBarrier.srcAccessMask = 0; + imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + imageMemoryBarrier.srcQueueFamilyIndex = vulkanDevice->queueFamilyIndices.compute; + imageMemoryBarrier.dstQueueFamilyIndex = vulkanDevice->queueFamilyIndices.graphics; + vkCmdPipelineBarrier( + drawCmdBuffers[i], + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_FLAGS_NONE, + 0, nullptr, + 0, nullptr, + 1, &imageMemoryBarrier); + } + else + { + // Combined barrier on single queue family + imageMemoryBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; + imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + vkCmdPipelineBarrier( + drawCmdBuffers[i], + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_FLAGS_NONE, + 0, nullptr, + 0, nullptr, + 1, &imageMemoryBarrier); + } vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); @@ -252,6 +277,23 @@ public: vkCmdEndRenderPass(drawCmdBuffers[i]); + if (vulkanDevice->queueFamilyIndices.graphics != vulkanDevice->queueFamilyIndices.compute) + { + // Release barrier from graphics queue + imageMemoryBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; + imageMemoryBarrier.dstAccessMask = 0; + imageMemoryBarrier.srcQueueFamilyIndex = vulkanDevice->queueFamilyIndices.graphics; + imageMemoryBarrier.dstQueueFamilyIndex = vulkanDevice->queueFamilyIndices.compute; + vkCmdPipelineBarrier( + drawCmdBuffers[i], + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + VK_FLAGS_NONE, + 0, nullptr, + 0, nullptr, + 1, &imageMemoryBarrier); + } + VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); } @@ -262,12 +304,52 @@ public: VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); VK_CHECK_RESULT(vkBeginCommandBuffer(compute.commandBuffer, &cmdBufInfo)); + + VkImageMemoryBarrier imageMemoryBarrier = {}; + imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL; + imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; + imageMemoryBarrier.image = textureComputeTarget.image; + imageMemoryBarrier.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; + if (vulkanDevice->queueFamilyIndices.graphics != vulkanDevice->queueFamilyIndices.compute) + { + // Acquire barrier for compute queue + imageMemoryBarrier.srcAccessMask = 0; + imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT; + imageMemoryBarrier.srcQueueFamilyIndex = vulkanDevice->queueFamilyIndices.graphics; + imageMemoryBarrier.dstQueueFamilyIndex = vulkanDevice->queueFamilyIndices.compute; + vkCmdPipelineBarrier( + compute.commandBuffer, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_FLAGS_NONE, + 0, nullptr, + 0, nullptr, + 1, &imageMemoryBarrier); + } vkCmdBindPipeline(compute.commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, compute.pipeline); vkCmdBindDescriptorSets(compute.commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, compute.pipelineLayout, 0, 1, &compute.descriptorSet, 0, 0); vkCmdDispatch(compute.commandBuffer, textureComputeTarget.width / 16, textureComputeTarget.height / 16, 1); + if (vulkanDevice->queueFamilyIndices.graphics != vulkanDevice->queueFamilyIndices.compute) + { + // Release barrier from compute queue + imageMemoryBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; + imageMemoryBarrier.dstAccessMask = 0; + imageMemoryBarrier.srcQueueFamilyIndex = vulkanDevice->queueFamilyIndices.compute; + imageMemoryBarrier.dstQueueFamilyIndex = vulkanDevice->queueFamilyIndices.graphics; + vkCmdPipelineBarrier( + compute.commandBuffer, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + VK_FLAGS_NONE, + 0, nullptr, + 0, nullptr, + 1, &imageMemoryBarrier); + } + vkEndCommandBuffer(compute.commandBuffer); } @@ -361,6 +443,30 @@ public: copyCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); copyRegion.size = storageBufferSize; vkCmdCopyBuffer(copyCmd, stagingBuffer.buffer, compute.storageBuffers.planes.buffer, 1, ©Region); + // Add an initial release barrier to the graphics queue, + // so that when the compute command buffer executes for the first time + // it doesn't complain about a lack of a corresponding "release" to its "acquire" + if (vulkanDevice->queueFamilyIndices.graphics != vulkanDevice->queueFamilyIndices.compute) + { + VkImageMemoryBarrier imageMemoryBarrier = {}; + imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL; + imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; + imageMemoryBarrier.image = textureComputeTarget.image; + imageMemoryBarrier.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; + imageMemoryBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; + imageMemoryBarrier.dstAccessMask = 0; + imageMemoryBarrier.srcQueueFamilyIndex = vulkanDevice->queueFamilyIndices.graphics; + imageMemoryBarrier.dstQueueFamilyIndex = vulkanDevice->queueFamilyIndices.compute; + vkCmdPipelineBarrier( + copyCmd, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + VK_FLAGS_NONE, + 0, nullptr, + 0, nullptr, + 1, &imageMemoryBarrier); + } vulkanDevice->flushCommandBuffer(copyCmd, queue, true); stagingBuffer.destroy(); @@ -689,9 +795,9 @@ public: void prepare() { VulkanExampleBase::prepare(); + prepareTextureTarget(&textureComputeTarget, TEX_DIM, TEX_DIM, VK_FORMAT_R8G8B8A8_UNORM); prepareStorageBuffers(); prepareUniformBuffers(); - prepareTextureTarget(&textureComputeTarget, TEX_DIM, TEX_DIM, VK_FORMAT_R8G8B8A8_UNORM); setupDescriptorSetLayout(); preparePipelines(); setupDescriptorPool(); From 279c95422d1f3e2b849d6594fe2e71633a089230 Mon Sep 17 00:00:00 2001 From: Stephen Saunders Date: Mon, 13 Jun 2022 23:04:53 -0400 Subject: [PATCH 18/36] Implement viewChanged() in multiple examples for proper window resize handling, fix triangle example resizing on macOS --- examples/computeshader/computeshader.cpp | 6 +++ .../conditionalrender/conditionalrender.cpp | 5 +++ examples/debugmarker/debugmarker.cpp | 6 ++- examples/deferred/deferred.cpp | 5 +++ .../deferredmultisampling.cpp | 5 +++ examples/deferredshadows/deferredshadows.cpp | 5 +++ .../descriptorindexing/descriptorindexing.cpp | 5 +++ examples/displacement/displacement.cpp | 8 +++- .../distancefieldfonts/distancefieldfonts.cpp | 3 +- examples/gltfloading/gltfloading.cpp | 5 +++ .../gltfscenerendering/gltfscenerendering.cpp | 7 ++- .../gltfscenerendering/gltfscenerendering.h | 1 + examples/gltfskinning/gltfskinning.cpp | 7 ++- examples/gltfskinning/gltfskinning.h | 1 + examples/hdr/hdr.cpp | 5 +++ examples/indirectdraw/indirectdraw.cpp | 7 ++- .../inlineuniformblocks.cpp | 7 ++- .../inputattachments/inputattachments.cpp | 5 +++ examples/instancing/instancing.cpp | 7 ++- examples/multisampling/multisampling.cpp | 5 +++ examples/multithreading/multithreading.cpp | 7 ++- examples/multiview/multiview.cpp | 5 +++ examples/oit/oit.cpp | 4 +- examples/particlefire/particlefire.cpp | 7 ++- examples/pbrtexture/pbrtexture.cpp | 5 +++ examples/pipelines/pipelines.cpp | 8 +++- examples/pushdescriptors/pushdescriptors.cpp | 5 +++ .../specializationconstants.cpp | 4 +- .../sphericalenvmapping.cpp | 7 ++- examples/ssao/ssao.cpp | 6 +++ examples/subpasses/subpasses.cpp | 6 +++ .../terraintessellation.cpp | 7 ++- examples/tessellation/tessellation.cpp | 6 +++ examples/textoverlay/textoverlay.cpp | 19 +++++--- examples/texture3d/texture3d.cpp | 5 +++ examples/texturearray/texturearray.cpp | 6 ++- .../texturecubemaparray.cpp | 7 ++- .../texturesparseresidency.cpp | 5 +++ .../texturesparseresidency.h | 1 + examples/triangle/triangle.cpp | 44 ++++++++++++++----- .../vertexattributes/vertexattributes.cpp | 7 ++- examples/vertexattributes/vertexattributes.h | 1 + 42 files changed, 240 insertions(+), 37 deletions(-) diff --git a/examples/computeshader/computeshader.cpp b/examples/computeshader/computeshader.cpp index 7e9b4d47..b9a33210 100644 --- a/examples/computeshader/computeshader.cpp +++ b/examples/computeshader/computeshader.cpp @@ -654,6 +654,12 @@ public: } } + virtual void viewChanged() + { + camera.setPerspective(60.0f, (float)width * 0.5f / (float)height, 1.0f, 256.0f); + updateUniformBuffers(); + } + virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) { if (overlay->header("Settings")) { diff --git a/examples/conditionalrender/conditionalrender.cpp b/examples/conditionalrender/conditionalrender.cpp index 3c8195e9..5b3613b5 100644 --- a/examples/conditionalrender/conditionalrender.cpp +++ b/examples/conditionalrender/conditionalrender.cpp @@ -330,6 +330,11 @@ public: } } + virtual void viewChanged() + { + updateUniformBuffers(); + } + virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) { if (overlay->header("Visibility")) { diff --git a/examples/debugmarker/debugmarker.cpp b/examples/debugmarker/debugmarker.cpp index dc5e42a8..8b7c7348 100644 --- a/examples/debugmarker/debugmarker.cpp +++ b/examples/debugmarker/debugmarker.cpp @@ -777,6 +777,10 @@ public: updateUniformBuffers(); } + virtual void viewChanged() + { + updateUniformBuffers(); + } virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) { @@ -796,4 +800,4 @@ public: } }; -VULKAN_EXAMPLE_MAIN() \ No newline at end of file +VULKAN_EXAMPLE_MAIN() diff --git a/examples/deferred/deferred.cpp b/examples/deferred/deferred.cpp index 0994e2f9..18bf1874 100644 --- a/examples/deferred/deferred.cpp +++ b/examples/deferred/deferred.cpp @@ -809,6 +809,11 @@ public: } } + virtual void viewChanged() + { + updateUniformBufferOffscreen(); + } + virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) { if (overlay->header("Settings")) { diff --git a/examples/deferredmultisampling/deferredmultisampling.cpp b/examples/deferredmultisampling/deferredmultisampling.cpp index 3e95ae45..0b6f6805 100644 --- a/examples/deferredmultisampling/deferredmultisampling.cpp +++ b/examples/deferredmultisampling/deferredmultisampling.cpp @@ -647,6 +647,11 @@ public: } } + virtual void viewChanged() + { + updateUniformBufferOffscreen(); + } + virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) { if (overlay->header("Settings")) { diff --git a/examples/deferredshadows/deferredshadows.cpp b/examples/deferredshadows/deferredshadows.cpp index 033ce34a..ac7a017b 100644 --- a/examples/deferredshadows/deferredshadows.cpp +++ b/examples/deferredshadows/deferredshadows.cpp @@ -808,6 +808,11 @@ public: } } + virtual void viewChanged() + { + updateUniformBufferOffscreen(); + } + virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) { if (overlay->header("Settings")) { diff --git a/examples/descriptorindexing/descriptorindexing.cpp b/examples/descriptorindexing/descriptorindexing.cpp index 354d3b55..d0a016ac 100644 --- a/examples/descriptorindexing/descriptorindexing.cpp +++ b/examples/descriptorindexing/descriptorindexing.cpp @@ -409,6 +409,11 @@ public: updateUniformBuffersCamera(); } + virtual void viewChanged() + { + updateUniformBuffersCamera(); + } + }; VULKAN_EXAMPLE_MAIN() \ No newline at end of file diff --git a/examples/displacement/displacement.cpp b/examples/displacement/displacement.cpp index 125ff200..2ae6b0ff 100644 --- a/examples/displacement/displacement.cpp +++ b/examples/displacement/displacement.cpp @@ -385,6 +385,12 @@ public: updateUniformBuffers(); } } + + virtual void viewChanged() + { + updateUniformBuffers(); + } + virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) { if (overlay->header("Settings")) { @@ -408,4 +414,4 @@ public: } }; -VULKAN_EXAMPLE_MAIN() \ No newline at end of file +VULKAN_EXAMPLE_MAIN() diff --git a/examples/distancefieldfonts/distancefieldfonts.cpp b/examples/distancefieldfonts/distancefieldfonts.cpp index 30cafc75..d3c67d9f 100644 --- a/examples/distancefieldfonts/distancefieldfonts.cpp +++ b/examples/distancefieldfonts/distancefieldfonts.cpp @@ -643,6 +643,7 @@ public: virtual void viewChanged() { + camera.setPerspective(splitScreen ? 30.0f : 45.0f, (float)width / (float)(height * ((splitScreen) ? 0.5f : 1.0f)), 1.0f, 256.0f); updateUniformBuffers(); } @@ -663,4 +664,4 @@ public: } }; -VULKAN_EXAMPLE_MAIN() \ No newline at end of file +VULKAN_EXAMPLE_MAIN() diff --git a/examples/gltfloading/gltfloading.cpp b/examples/gltfloading/gltfloading.cpp index c2144ded..1aa42647 100644 --- a/examples/gltfloading/gltfloading.cpp +++ b/examples/gltfloading/gltfloading.cpp @@ -729,6 +729,11 @@ public: } } + virtual void viewChanged() + { + updateUniformBuffers(); + } + virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) { if (overlay->header("Settings")) { diff --git a/examples/gltfscenerendering/gltfscenerendering.cpp b/examples/gltfscenerendering/gltfscenerendering.cpp index 64f062f1..02b655d5 100644 --- a/examples/gltfscenerendering/gltfscenerendering.cpp +++ b/examples/gltfscenerendering/gltfscenerendering.cpp @@ -631,6 +631,11 @@ void VulkanExample::render() } } +void VulkanExample::viewChanged() +{ + updateUniformBuffers(); +} + void VulkanExample::OnUpdateUIOverlay(vks::UIOverlay* overlay) { if (overlay->header("Visibility")) { @@ -659,4 +664,4 @@ void VulkanExample::OnUpdateUIOverlay(vks::UIOverlay* overlay) } } -VULKAN_EXAMPLE_MAIN() \ No newline at end of file +VULKAN_EXAMPLE_MAIN() diff --git a/examples/gltfscenerendering/gltfscenerendering.h b/examples/gltfscenerendering/gltfscenerendering.h index e02abfe6..1d6cffe3 100644 --- a/examples/gltfscenerendering/gltfscenerendering.h +++ b/examples/gltfscenerendering/gltfscenerendering.h @@ -162,5 +162,6 @@ public: void updateUniformBuffers(); void prepare(); virtual void render(); + virtual void viewChanged(); virtual void OnUpdateUIOverlay(vks::UIOverlay* overlay); }; diff --git a/examples/gltfskinning/gltfskinning.cpp b/examples/gltfskinning/gltfskinning.cpp index d7988b83..f019395e 100644 --- a/examples/gltfskinning/gltfskinning.cpp +++ b/examples/gltfskinning/gltfskinning.cpp @@ -995,6 +995,11 @@ void VulkanExample::render() } } +void VulkanExample::viewChanged() +{ + updateUniformBuffers(); +} + void VulkanExample::OnUpdateUIOverlay(vks::UIOverlay *overlay) { if (overlay->header("Settings")) @@ -1006,4 +1011,4 @@ void VulkanExample::OnUpdateUIOverlay(vks::UIOverlay *overlay) } } -VULKAN_EXAMPLE_MAIN() \ No newline at end of file +VULKAN_EXAMPLE_MAIN() diff --git a/examples/gltfskinning/gltfskinning.h b/examples/gltfskinning/gltfskinning.h index 9423c01c..67f9c070 100644 --- a/examples/gltfskinning/gltfskinning.h +++ b/examples/gltfskinning/gltfskinning.h @@ -232,5 +232,6 @@ class VulkanExample : public VulkanExampleBase void updateUniformBuffers(); void prepare(); virtual void render(); + virtual void viewChanged(); virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay); }; diff --git a/examples/hdr/hdr.cpp b/examples/hdr/hdr.cpp index cda5b452..304a069c 100644 --- a/examples/hdr/hdr.cpp +++ b/examples/hdr/hdr.cpp @@ -870,6 +870,11 @@ public: updateUniformBuffers(); } + virtual void viewChanged() + { + updateUniformBuffers(); + } + virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) { if (overlay->header("Settings")) { diff --git a/examples/indirectdraw/indirectdraw.cpp b/examples/indirectdraw/indirectdraw.cpp index c5e373a9..4baee4aa 100644 --- a/examples/indirectdraw/indirectdraw.cpp +++ b/examples/indirectdraw/indirectdraw.cpp @@ -499,6 +499,11 @@ public: } } + virtual void viewChanged() + { + updateUniformBuffer(true); + } + virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) { if (!vulkanDevice->features.multiDrawIndirect) { @@ -512,4 +517,4 @@ public: } }; -VULKAN_EXAMPLE_MAIN() \ No newline at end of file +VULKAN_EXAMPLE_MAIN() diff --git a/examples/inlineuniformblocks/inlineuniformblocks.cpp b/examples/inlineuniformblocks/inlineuniformblocks.cpp index 1dafe711..04b11bf7 100644 --- a/examples/inlineuniformblocks/inlineuniformblocks.cpp +++ b/examples/inlineuniformblocks/inlineuniformblocks.cpp @@ -357,6 +357,11 @@ public: updateUniformBuffers(); } + virtual void viewChanged() + { + updateUniformBuffers(); + } + /* [POI] Update descriptor sets at runtime */ @@ -401,4 +406,4 @@ public: }; -VULKAN_EXAMPLE_MAIN() \ No newline at end of file +VULKAN_EXAMPLE_MAIN() diff --git a/examples/inputattachments/inputattachments.cpp b/examples/inputattachments/inputattachments.cpp index f0927815..3fd2c828 100644 --- a/examples/inputattachments/inputattachments.cpp +++ b/examples/inputattachments/inputattachments.cpp @@ -606,6 +606,11 @@ public: } } + virtual void viewChanged() + { + updateUniformBuffers(); + } + virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) { if (overlay->header("Settings")) { diff --git a/examples/instancing/instancing.cpp b/examples/instancing/instancing.cpp index d8dbe2b7..74feb2f7 100644 --- a/examples/instancing/instancing.cpp +++ b/examples/instancing/instancing.cpp @@ -482,6 +482,11 @@ public: } } + virtual void viewChanged() + { + updateUniformBuffer(true); + } + virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) { if (overlay->header("Statistics")) { @@ -490,4 +495,4 @@ public: } }; -VULKAN_EXAMPLE_MAIN() \ No newline at end of file +VULKAN_EXAMPLE_MAIN() diff --git a/examples/multisampling/multisampling.cpp b/examples/multisampling/multisampling.cpp index f73cef79..26e1691a 100644 --- a/examples/multisampling/multisampling.cpp +++ b/examples/multisampling/multisampling.cpp @@ -541,6 +541,11 @@ public: } } + virtual void viewChanged() + { + updateUniformBuffers(); + } + // Returns the maximum sample count usable by the platform VkSampleCountFlagBits getMaxUsableSampleCount() { diff --git a/examples/multithreading/multithreading.cpp b/examples/multithreading/multithreading.cpp index 38ef02f2..c60d18a9 100644 --- a/examples/multithreading/multithreading.cpp +++ b/examples/multithreading/multithreading.cpp @@ -527,6 +527,11 @@ public: } } + virtual void viewChanged() + { + updateMatrices(); + } + virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) { if (overlay->header("Statistics")) { @@ -539,4 +544,4 @@ public: } }; -VULKAN_EXAMPLE_MAIN() \ No newline at end of file +VULKAN_EXAMPLE_MAIN() diff --git a/examples/multiview/multiview.cpp b/examples/multiview/multiview.cpp index 17a4a676..b9397cfb 100644 --- a/examples/multiview/multiview.cpp +++ b/examples/multiview/multiview.cpp @@ -738,6 +738,11 @@ public: } } + virtual void viewChanged() + { + updateUniformBuffers(); + } + virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) { if (overlay->header("Settings")) { diff --git a/examples/oit/oit.cpp b/examples/oit/oit.cpp index 2743f974..77bdd68e 100644 --- a/examples/oit/oit.cpp +++ b/examples/oit/oit.cpp @@ -507,7 +507,7 @@ private: vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, NULL); } - void buildCommandBuffers() + void buildCommandBuffers() override { if (resized) return; @@ -656,4 +656,4 @@ private: VkDeviceSize objectUniformBufferSize; }; -VULKAN_EXAMPLE_MAIN() \ No newline at end of file +VULKAN_EXAMPLE_MAIN() diff --git a/examples/particlefire/particlefire.cpp b/examples/particlefire/particlefire.cpp index b4b9bb55..e966d545 100644 --- a/examples/particlefire/particlefire.cpp +++ b/examples/particlefire/particlefire.cpp @@ -589,6 +589,11 @@ public: updateUniformBuffers(); } } + + virtual void viewChanged() + { + updateUniformBuffers(); + } }; -VULKAN_EXAMPLE_MAIN() \ No newline at end of file +VULKAN_EXAMPLE_MAIN() diff --git a/examples/pbrtexture/pbrtexture.cpp b/examples/pbrtexture/pbrtexture.cpp index 5be56716..e69c8b78 100644 --- a/examples/pbrtexture/pbrtexture.cpp +++ b/examples/pbrtexture/pbrtexture.cpp @@ -1340,6 +1340,11 @@ public: } } + virtual void viewChanged() + { + updateUniformBuffers(); + } + virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) { if (overlay->header("Settings")) { diff --git a/examples/pipelines/pipelines.cpp b/examples/pipelines/pipelines.cpp index 68d0415a..13034073 100644 --- a/examples/pipelines/pipelines.cpp +++ b/examples/pipelines/pipelines.cpp @@ -334,6 +334,12 @@ public: } } + virtual void viewChanged() + { + camera.setPerspective(60.0f, (float)(width / 3.0f) / (float)height, 0.1f, 256.0f); + updateUniformBuffers(); + } + virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) { if (!deviceFeatures.fillModeNonSolid) { @@ -344,4 +350,4 @@ public: } }; -VULKAN_EXAMPLE_MAIN() \ No newline at end of file +VULKAN_EXAMPLE_MAIN() diff --git a/examples/pushdescriptors/pushdescriptors.cpp b/examples/pushdescriptors/pushdescriptors.cpp index b1979828..a6f6094d 100644 --- a/examples/pushdescriptors/pushdescriptors.cpp +++ b/examples/pushdescriptors/pushdescriptors.cpp @@ -337,6 +337,11 @@ public: } } + virtual void viewChanged() + { + updateUniformBuffers(); + } + virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) { if (overlay->header("Settings")) { diff --git a/examples/specializationconstants/specializationconstants.cpp b/examples/specializationconstants/specializationconstants.cpp index 0384086d..d0692d03 100644 --- a/examples/specializationconstants/specializationconstants.cpp +++ b/examples/specializationconstants/specializationconstants.cpp @@ -320,10 +320,10 @@ public: } } - virtual void windowResized() + virtual void viewChanged() { updateUniformBuffers(); } }; -VULKAN_EXAMPLE_MAIN() \ No newline at end of file +VULKAN_EXAMPLE_MAIN() diff --git a/examples/sphericalenvmapping/sphericalenvmapping.cpp b/examples/sphericalenvmapping/sphericalenvmapping.cpp index 883184aa..9bf8ce3e 100644 --- a/examples/sphericalenvmapping/sphericalenvmapping.cpp +++ b/examples/sphericalenvmapping/sphericalenvmapping.cpp @@ -277,6 +277,11 @@ public: } } + virtual void viewChanged() + { + updateUniformBuffers(); + } + virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) { if (overlay->header("Settings")) { @@ -288,4 +293,4 @@ public: }; -VULKAN_EXAMPLE_MAIN() \ No newline at end of file +VULKAN_EXAMPLE_MAIN() diff --git a/examples/ssao/ssao.cpp b/examples/ssao/ssao.cpp index 92558908..be9e81ae 100644 --- a/examples/ssao/ssao.cpp +++ b/examples/ssao/ssao.cpp @@ -944,6 +944,12 @@ public: } } + virtual void viewChanged() + { + updateUniformBufferMatrices(); + updateUniformBufferSSAOParams(); + } + virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) { if (overlay->header("Settings")) { diff --git a/examples/subpasses/subpasses.cpp b/examples/subpasses/subpasses.cpp index d1e4ea93..9f59df3c 100644 --- a/examples/subpasses/subpasses.cpp +++ b/examples/subpasses/subpasses.cpp @@ -903,6 +903,12 @@ public: } } + virtual void viewChanged() + { + updateUniformBufferDeferredMatrices(); + updateUniformBufferDeferredLights(); + } + virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) { if (overlay->header("Subpasses")) { diff --git a/examples/terraintessellation/terraintessellation.cpp b/examples/terraintessellation/terraintessellation.cpp index 80a79e27..30bcbd1e 100644 --- a/examples/terraintessellation/terraintessellation.cpp +++ b/examples/terraintessellation/terraintessellation.cpp @@ -828,6 +828,11 @@ public: } } + virtual void viewChanged() + { + updateUniformBuffers(); + } + virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) { if (overlay->header("Settings")) { @@ -853,4 +858,4 @@ public: } }; -VULKAN_EXAMPLE_MAIN() \ No newline at end of file +VULKAN_EXAMPLE_MAIN() diff --git a/examples/tessellation/tessellation.cpp b/examples/tessellation/tessellation.cpp index 444a0789..87b5b8fd 100644 --- a/examples/tessellation/tessellation.cpp +++ b/examples/tessellation/tessellation.cpp @@ -326,6 +326,12 @@ public: } } + virtual void viewChanged() + { + camera.setPerspective(45.0f, (float)(width * ((splitScreen) ? 0.5f : 1.0f)) / (float)height, 0.1f, 256.0f); + updateUniformBuffers(); + } + virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) { if (overlay->header("Settings")) { diff --git a/examples/textoverlay/textoverlay.cpp b/examples/textoverlay/textoverlay.cpp index 7672b2b8..4c8fa1e4 100644 --- a/examples/textoverlay/textoverlay.cpp +++ b/examples/textoverlay/textoverlay.cpp @@ -514,6 +514,8 @@ public: case alignCenter: x -= textWidth / 2.0f; break; + case alignLeft: + break; } // Generate a uv mapped quad per char in the new text @@ -885,6 +887,10 @@ public: if (!prepared) return; draw(); + if (camera.updated) + { + updateUniformBuffers(); + } if (frameCounter == 0) { vkDeviceWaitIdle(device); @@ -892,13 +898,6 @@ public: } } - virtual void viewChanged() - { - vkDeviceWaitIdle(device); - updateUniformBuffers(); - updateTextOverlay(); - } - virtual void windowResized() { // SRS - Recreate text overlay resources in case number of swapchain images has changed on resize @@ -906,6 +905,12 @@ public: prepareTextOverlay(); } + virtual void viewChanged() + { + updateUniformBuffers(); + updateTextOverlay(); + } + #if !defined(__ANDROID__) virtual void keyPressed(uint32_t keyCode) { diff --git a/examples/texture3d/texture3d.cpp b/examples/texture3d/texture3d.cpp index f2f672e2..773848c2 100644 --- a/examples/texture3d/texture3d.cpp +++ b/examples/texture3d/texture3d.cpp @@ -773,6 +773,11 @@ public: updateUniformBuffers(camera.updated); } + virtual void viewChanged() + { + updateUniformBuffers(true); + } + virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) { if (overlay->header("Settings")) { diff --git a/examples/texturearray/texturearray.cpp b/examples/texturearray/texturearray.cpp index 41cd5392..921addea 100644 --- a/examples/texturearray/texturearray.cpp +++ b/examples/texturearray/texturearray.cpp @@ -550,6 +550,10 @@ public: updateUniformBuffersCamera(); } + virtual void viewChanged() + { + updateUniformBuffersCamera(); + } }; -VULKAN_EXAMPLE_MAIN() \ No newline at end of file +VULKAN_EXAMPLE_MAIN() diff --git a/examples/texturecubemaparray/texturecubemaparray.cpp b/examples/texturecubemaparray/texturecubemaparray.cpp index 6d9c5494..6e649d82 100644 --- a/examples/texturecubemaparray/texturecubemaparray.cpp +++ b/examples/texturecubemaparray/texturecubemaparray.cpp @@ -529,6 +529,11 @@ public: } } + virtual void viewChanged() + { + updateUniformBuffers(); + } + virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) { if (overlay->header("Settings")) { @@ -548,4 +553,4 @@ public: } }; -VULKAN_EXAMPLE_MAIN() \ No newline at end of file +VULKAN_EXAMPLE_MAIN() diff --git a/examples/texturesparseresidency/texturesparseresidency.cpp b/examples/texturesparseresidency/texturesparseresidency.cpp index 0875a6ec..10889474 100644 --- a/examples/texturesparseresidency/texturesparseresidency.cpp +++ b/examples/texturesparseresidency/texturesparseresidency.cpp @@ -708,6 +708,11 @@ void VulkanExample::render() } } +void VulkanExample::viewChanged() +{ + updateUniformBuffers(); +} + // Fills a buffer with random colors void VulkanExample::randomPattern(uint8_t* buffer, uint32_t width, uint32_t height) { diff --git a/examples/texturesparseresidency/texturesparseresidency.h b/examples/texturesparseresidency/texturesparseresidency.h index e061dc9e..5da19e18 100644 --- a/examples/texturesparseresidency/texturesparseresidency.h +++ b/examples/texturesparseresidency/texturesparseresidency.h @@ -116,6 +116,7 @@ public: void updateUniformBuffers(); void prepare(); virtual void render(); + virtual void viewChanged(); void uploadContent(VirtualTexturePage page, VkImage image); void fillRandomPages(); void fillMipTail(); diff --git a/examples/triangle/triangle.cpp b/examples/triangle/triangle.cpp index 6b16b296..6d0e35d3 100644 --- a/examples/triangle/triangle.cpp +++ b/examples/triangle/triangle.cpp @@ -109,7 +109,7 @@ public: // Fences // Used to check the completion of queue operations (e.g. command buffer execution) - std::vector waitFences; + std::vector queueCompleteFences; VulkanExample() : VulkanExampleBase(ENABLE_VALIDATION) { @@ -148,7 +148,7 @@ public: vkDestroySemaphore(device, presentCompleteSemaphore, nullptr); vkDestroySemaphore(device, renderCompleteSemaphore, nullptr); - for (auto& fence : waitFences) + for (auto& fence : queueCompleteFences) { vkDestroyFence(device, fence, nullptr); } @@ -196,8 +196,8 @@ public: fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; // Create in signaled state so we don't wait on first render of each command buffer fenceCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; - waitFences.resize(drawCmdBuffers.size()); - for (auto& fence : waitFences) + queueCompleteFences.resize(drawCmdBuffers.size()); + for (auto& fence : queueCompleteFences) { VK_CHECK_RESULT(vkCreateFence(device, &fenceCreateInfo, nullptr, &fence)); } @@ -337,6 +337,16 @@ public: void draw() { +#if defined(VK_USE_PLATFORM_MACOS_MVK) + // SRS - on macOS use swapchain helper function with common semaphores/fences for proper resize handling + // Get next image in the swap chain (back/front buffer) + prepareFrame(); + + // Use a fence to wait until the command buffer has finished execution before using it again + VK_CHECK_RESULT(vkWaitForFences(device, 1, &waitFences[currentBuffer], VK_TRUE, UINT64_MAX)); + VK_CHECK_RESULT(vkResetFences(device, 1, &waitFences[currentBuffer])); +#else + // SRS - on other platforms use original bare code with local semaphores/fences for illustrative purposes // Get next image in the swap chain (back/front buffer) VkResult acquire = swapChain.acquireNextImage(presentCompleteSemaphore, ¤tBuffer); if (!((acquire == VK_SUCCESS) || (acquire == VK_SUBOPTIMAL_KHR))) { @@ -344,8 +354,9 @@ public: } // Use a fence to wait until the command buffer has finished execution before using it again - VK_CHECK_RESULT(vkWaitForFences(device, 1, &waitFences[currentBuffer], VK_TRUE, UINT64_MAX)); - VK_CHECK_RESULT(vkResetFences(device, 1, &waitFences[currentBuffer])); + VK_CHECK_RESULT(vkWaitForFences(device, 1, &queueCompleteFences[currentBuffer], VK_TRUE, UINT64_MAX)); + VK_CHECK_RESULT(vkResetFences(device, 1, &queueCompleteFences[currentBuffer])); +#endif // Pipeline stage at which the queue submission will wait (via pWaitSemaphores) VkPipelineStageFlags waitStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; @@ -353,16 +364,29 @@ public: VkSubmitInfo submitInfo = {}; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submitInfo.pWaitDstStageMask = &waitStageMask; // Pointer to the list of pipeline stages that the semaphore waits will occur at - submitInfo.pWaitSemaphores = &presentCompleteSemaphore; // Semaphore(s) to wait upon before the submitted command buffer starts executing submitInfo.waitSemaphoreCount = 1; // One wait semaphore - submitInfo.pSignalSemaphores = &renderCompleteSemaphore; // Semaphore(s) to be signaled when command buffers have completed submitInfo.signalSemaphoreCount = 1; // One signal semaphore submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; // Command buffers(s) to execute in this batch (submission) submitInfo.commandBufferCount = 1; // One command buffer +#if defined(VK_USE_PLATFORM_MACOS_MVK) + // SRS - on macOS use swapchain helper function with common semaphores/fences for proper resize handling + submitInfo.pWaitSemaphores = &semaphores.presentComplete; // Semaphore(s) to wait upon before the submitted command buffer starts executing + submitInfo.pSignalSemaphores = &semaphores.renderComplete; // Semaphore(s) to be signaled when command buffers have completed + // Submit to the graphics queue passing a wait fence VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, waitFences[currentBuffer])); + // Present the current buffer to the swap chain + submitFrame(); +#else + // SRS - on other platforms use original bare code with local semaphores/fences for illustrative purposes + submitInfo.pWaitSemaphores = &presentCompleteSemaphore; // Semaphore(s) to wait upon before the submitted command buffer starts executing + submitInfo.pSignalSemaphores = &renderCompleteSemaphore; // Semaphore(s) to be signaled when command buffers have completed + + // Submit to the graphics queue passing a wait fence + VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, queueCompleteFences[currentBuffer])); + // Present the current buffer to the swap chain // Pass the semaphore signaled by the command buffer submission from the submit info as the wait semaphore for swap chain presentation // This ensures that the image is not presented to the windowing system until all commands have been submitted @@ -370,7 +394,7 @@ public: if (!((present == VK_SUCCESS) || (present == VK_SUBOPTIMAL_KHR))) { VK_CHECK_RESULT(present); } - +#endif } // Prepare vertex and index buffers for an indexed triangle @@ -1235,7 +1259,7 @@ int main(const int argc, const char *argv[]) vulkanExample->setupWindow(nullptr); vulkanExample->prepare(); vulkanExample->renderLoop(); - delete(vulkanExample); + //delete(vulkanExample); // SRS - vulkanExample deleted by AppDelegate termination event handler } return 0; } diff --git a/examples/vertexattributes/vertexattributes.cpp b/examples/vertexattributes/vertexattributes.cpp index b10f9991..5607b051 100644 --- a/examples/vertexattributes/vertexattributes.cpp +++ b/examples/vertexattributes/vertexattributes.cpp @@ -580,6 +580,11 @@ void VulkanExample::render() } } +void VulkanExample::viewChanged() +{ + updateUniformBuffers(); +} + void VulkanExample::OnUpdateUIOverlay(vks::UIOverlay* overlay) { if (overlay->header("Vertex buffer attributes")) { @@ -596,4 +601,4 @@ void VulkanExample::OnUpdateUIOverlay(vks::UIOverlay* overlay) } } -VULKAN_EXAMPLE_MAIN() \ No newline at end of file +VULKAN_EXAMPLE_MAIN() diff --git a/examples/vertexattributes/vertexattributes.h b/examples/vertexattributes/vertexattributes.h index 97abf1b3..d51f96ec 100644 --- a/examples/vertexattributes/vertexattributes.h +++ b/examples/vertexattributes/vertexattributes.h @@ -139,5 +139,6 @@ public: void loadSceneNode(const tinygltf::Node& inputNode, const tinygltf::Model& input, Node* parent); void drawSceneNode(VkCommandBuffer commandBuffer, Node node); virtual void render(); + virtual void viewChanged(); virtual void OnUpdateUIOverlay(vks::UIOverlay* overlay); }; From 8bc8d14cf28198ea43a8dc5338266d97fb4eb420 Mon Sep 17 00:00:00 2001 From: Stephen Saunders Date: Mon, 20 Jun 2022 16:44:34 -0400 Subject: [PATCH 19/36] macOS retina scaling fixes, M1 Vulkan vsync workaround, CMakeLists OpenMP path fix for Apple --- base/VulkanSwapChain.cpp | 8 ++++++-- base/VulkanSwapChain.h | 4 ++++ base/VulkanUIOverlay.cpp | 8 +++++--- base/vulkanexamplebase.cpp | 2 +- examples/CMakeLists.txt | 8 ++++---- examples/gltfscenerendering/gltfscenerendering.cpp | 2 +- xcode/MVKExample.cpp | 7 ++++--- xcode/MVKExample.h | 2 +- xcode/ios/DemoViewController.mm | 2 +- xcode/macos/DemoViewController.mm | 11 ++++++----- 10 files changed, 33 insertions(+), 21 deletions(-) diff --git a/base/VulkanSwapChain.cpp b/base/VulkanSwapChain.cpp index 9d2f92b5..e12405dd 100644 --- a/base/VulkanSwapChain.cpp +++ b/base/VulkanSwapChain.cpp @@ -291,8 +291,12 @@ void VulkanSwapChain::create(uint32_t *width, uint32_t *height, bool vsync, bool // Determine the number of images uint32_t desiredNumberOfSwapchainImages = surfCaps.minImageCount + 1; #if (defined(VK_USE_PLATFORM_MACOS_MVK) && defined(VK_EXAMPLE_XCODE_GENERATED)) - // SRS - Work around known MoltenVK issue re 2x frame rate when vsync (VK_PRESENT_MODE_FIFO_KHR) enabled in windowed mode - if (vsync && !fullscreen) + // SRS - Work around known MoltenVK issue re 2x frame rate when vsync (VK_PRESENT_MODE_FIFO_KHR) enabled + struct utsname sysInfo; + uname(&sysInfo); + // SRS - When vsync is on, use minImageCount when not in fullscreen or when running on Apple Silcon + // This forces swapchain image acquire frame rate to match display vsync frame rate + if (vsync && (!fullscreen || strcmp(sysInfo.machine, "arm64") == 0)) { desiredNumberOfSwapchainImages = surfCaps.minImageCount; } diff --git a/base/VulkanSwapChain.h b/base/VulkanSwapChain.h index 29eaeb1b..8d591100 100644 --- a/base/VulkanSwapChain.h +++ b/base/VulkanSwapChain.h @@ -23,6 +23,10 @@ #include "VulkanAndroid.h" #endif +#ifdef __APPLE__ +#include +#endif + typedef struct _SwapChainBuffers { VkImage image; VkImageView view; diff --git a/base/VulkanUIOverlay.cpp b/base/VulkanUIOverlay.cpp index b18e2a5a..65e7c7b7 100644 --- a/base/VulkanUIOverlay.cpp +++ b/base/VulkanUIOverlay.cpp @@ -78,8 +78,10 @@ namespace vks } #else const std::string filename = getAssetPath() + "Roboto-Medium.ttf"; - io.Fonts->AddFontFromFileTTF(filename.c_str(), 16.0f); -#endif + io.Fonts->AddFontFromFileTTF(filename.c_str(), 16.0f * scale); + ImGuiStyle& style = ImGui::GetStyle(); + style.ScaleAllSizes(scale); +#endif io.Fonts->GetTexDataAsRGBA32(&fontData, &texWidth, &texHeight); VkDeviceSize uploadSize = texWidth*texHeight * 4 * sizeof(char); @@ -492,4 +494,4 @@ namespace vks ImGui::TextV(formatstr, args); va_end(args); } -} \ No newline at end of file +} diff --git a/base/vulkanexamplebase.cpp b/base/vulkanexamplebase.cpp index 01c66c40..5878252d 100644 --- a/base/vulkanexamplebase.cpp +++ b/base/vulkanexamplebase.cpp @@ -688,7 +688,7 @@ void VulkanExampleBase::updateOverlay() ImGui::NewFrame(); ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0); - ImGui::SetNextWindowPos(ImVec2(10, 10)); + ImGui::SetNextWindowPos(ImVec2(10 * UIOverlay.scale, 10 * UIOverlay.scale)); ImGui::SetNextWindowSize(ImVec2(0, 0), ImGuiSetCond_FirstUseEver); ImGui::Begin("Vulkan Example", nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove); ImGui::TextUnformatted(title.c_str()); diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 0876bc24..7fa6373c 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -12,21 +12,21 @@ function(buildExample EXAMPLE_NAME) SET(MAIN_HEADER ${EXAMPLE_FOLDER}/${EXAMPLE_NAME}.h) ENDIF() if(APPLE) - # SRS - Use MacPorts paths as default since they are the same on x86 and Apple Silicon, can override on cmake command line - if(NOT OpenMP_omp_LIBRARY) + # SRS - Use MacPorts paths as default since the same on x86 and Apple Silicon, can override for homebrew on cmake command line + if(NOT OpenMP_omp_LIBRARY AND EXISTS /opt/local/lib/libomp/libomp.dylib) set(OpenMP_omp_LIBRARY /opt/local/lib/libomp/libomp.dylib) endif() if(CMAKE_C_COMPILER_ID MATCHES "Clang\$") set(OpenMP_C_FLAGS "-Xclang -fopenmp") set(OpenMP_C_LIB_NAMES "omp") - if(NOT OpenMP_C_INCLUDE_DIR) + if(NOT OpenMP_C_INCLUDE_DIR AND EXISTS /opt/local/include/libomp) set(OpenMP_C_INCLUDE_DIR /opt/local/include/libomp) endif() endif() if(CMAKE_CXX_COMPILER_ID MATCHES "Clang\$") set(OpenMP_CXX_FLAGS "-Xclang -fopenmp") set(OpenMP_CXX_LIB_NAMES "omp") - if(NOT OpenMP_CXX_INCLUDE_DIR) + if(NOT OpenMP_CXX_INCLUDE_DIR AND EXISTS /opt/local/include/libomp) set(OpenMP_CXX_INCLUDE_DIR /opt/local/include/libomp) endif() endif() diff --git a/examples/gltfscenerendering/gltfscenerendering.cpp b/examples/gltfscenerendering/gltfscenerendering.cpp index 02b655d5..8493c343 100644 --- a/examples/gltfscenerendering/gltfscenerendering.cpp +++ b/examples/gltfscenerendering/gltfscenerendering.cpp @@ -652,7 +652,7 @@ void VulkanExample::OnUpdateUIOverlay(vks::UIOverlay* overlay) ImGui::NewLine(); // POI: Create a list of glTF nodes for visibility toggle - ImGui::BeginChild("#nodelist", ImVec2(200.0f, 340.0f), false); + ImGui::BeginChild("#nodelist", ImVec2(0.0f, ImGui::GetTextLineHeightWithSpacing() * (glTFScene.nodes.size() + 4)), false); for (auto &node : glTFScene.nodes) { if (overlay->checkBox(node.name.c_str(), &node.visible)) diff --git a/xcode/MVKExample.cpp b/xcode/MVKExample.cpp index b4f5abb1..3073d2d9 100644 --- a/xcode/MVKExample.cpp +++ b/xcode/MVKExample.cpp @@ -113,13 +113,14 @@ void MVKExample::fullScreen(bool fullscreen) { _vulkanExample->settings.fullscreen = fullscreen; } -MVKExample::MVKExample(void* view) { +MVKExample::MVKExample(void* view, double scaleUI) { _vulkanExample = new VulkanExample(); - _vulkanExample->settings.vsync = true; // SRS - this iOS/macOS example uses displayLink vsync rendering - set before calling prepare() _vulkanExample->initVulkan(); _vulkanExample->setupWindow(view); + _vulkanExample->settings.vsync = true; // SRS - set vsync flag since this iOS/macOS example app uses displayLink vsync rendering + _vulkanExample->UIOverlay.scale = scaleUI; // SRS - set UIOverlay scale to maintain relative proportions/readability on retina displays _vulkanExample->prepare(); - _vulkanExample->renderLoop(); // SRS - this inits destWidth/destHeight/lastTimestamp/tPrevEnd, then falls through and returns + _vulkanExample->renderLoop(); // SRS - this inits destWidth/destHeight/lastTimestamp/tPrevEnd, then falls through and returns } MVKExample::~MVKExample() { diff --git a/xcode/MVKExample.h b/xcode/MVKExample.h index c505a96d..bdbf3a11 100644 --- a/xcode/MVKExample.h +++ b/xcode/MVKExample.h @@ -31,7 +31,7 @@ public: void fullScreen(bool fullscreen); // SRS - expose VulkanExampleBase::settings.fullscreen to DemoView (macOS only) - MVKExample(void* view); + MVKExample(void* view, double scaleUI); // SRS - support UIOverlay scaling parameter based on device and display type ~MVKExample(); protected: diff --git a/xcode/ios/DemoViewController.mm b/xcode/ios/DemoViewController.mm index 3e5e65d7..00328952 100644 --- a/xcode/ios/DemoViewController.mm +++ b/xcode/ios/DemoViewController.mm @@ -32,7 +32,7 @@ const std::string getAssetPath() { self.view.contentScaleFactor = UIScreen.mainScreen.nativeScale; - _mvkExample = new MVKExample(self.view); + _mvkExample = new MVKExample(self.view, 1.0f); // SRS - Use 1x scale factor for UIOverlay on iOS // SRS - Enable AppDelegate to call into DemoViewController for handling app lifecycle events (e.g. termination) auto appDelegate = (AppDelegate *)UIApplication.sharedApplication.delegate; diff --git a/xcode/macos/DemoViewController.mm b/xcode/macos/DemoViewController.mm index 53d9e21c..a0a8d308 100644 --- a/xcode/macos/DemoViewController.mm +++ b/xcode/macos/DemoViewController.mm @@ -27,6 +27,7 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, return kCVReturnSuccess; } +CALayer* layer; MVKExample* _mvkExample; #pragma mark - @@ -40,9 +41,9 @@ MVKExample* _mvkExample; -(void) viewDidLoad { [super viewDidLoad]; - self.view.wantsLayer = YES; // Back the view with a layer created by the makeBackingLayer method. + self.view.wantsLayer = YES; // Back the view with a layer created by the makeBackingLayer method (called immediately on set) - _mvkExample = new MVKExample(self.view); + _mvkExample = new MVKExample(self.view, layer.contentsScale); // SRS - Use backing layer scale factor for UIOverlay on macOS // SRS - Enable AppDelegate to call into DemoViewController for handling application lifecycle events (e.g. termination) auto appDelegate = (AppDelegate *)NSApplication.sharedApplication.delegate; @@ -75,7 +76,7 @@ MVKExample* _mvkExample; /** If the wantsLayer property is set to YES, this method will be invoked to return a layer instance. */ -(CALayer*) makeBackingLayer { - CALayer* layer = [self.class.layerClass layer]; + layer = [self.class.layerClass layer]; CGSize viewScale = [self convertSizeToBacking: CGSizeMake(1.0, 1.0)]; layer.contentsScale = MIN(viewScale.width, viewScale.height); return layer; @@ -108,8 +109,8 @@ MVKExample* _mvkExample; // SRS - Handle mouse events -(NSPoint) getMouseLocalPoint:(NSEvent*) theEvent { NSPoint location = [theEvent locationInWindow]; - NSPoint point = [self convertPoint:location fromView:nil]; - point.y = self.frame.size.height - point.y; + NSPoint point = [self convertPointToBacking:location]; + point.y = self.frame.size.height*self.window.backingScaleFactor - point.y; return point; } From a184bd7007c3a07d869df1e4586f7656b804fdf2 Mon Sep 17 00:00:00 2001 From: Stephen Saunders Date: Wed, 6 Jul 2022 21:35:07 -0400 Subject: [PATCH 20/36] Set viewUpdated=true for macOS scroll wheel, open vulkanExamples window in front of Xcode, accept mouse click-through on macOS --- base/vulkanexamplebase.cpp | 8 ++++++++ base/vulkanexamplebase.h | 2 +- xcode/MVKExample.cpp | 1 + 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/base/vulkanexamplebase.cpp b/base/vulkanexamplebase.cpp index 5878252d..2c2d350b 100644 --- a/base/vulkanexamplebase.cpp +++ b/base/vulkanexamplebase.cpp @@ -1549,6 +1549,8 @@ dispatch_group_t concurrentGroup; - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + [NSApp activateIgnoringOtherApps:YES]; // SRS - Make sure app window launches in front of Xcode window + concurrentGroup = dispatch_group_create(); dispatch_queue_t concurrentQueue = dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0); dispatch_group_async(concurrentGroup, concurrentQueue, ^{ @@ -1628,6 +1630,11 @@ static CVReturn displayLinkOutputCallback(CVDisplayLinkRef displayLink, const CV return YES; } +- (BOOL)acceptsFirstMouse:(NSEvent *)event +{ + return YES; +} + - (void)keyDown:(NSEvent*)event { switch (event.keyCode) @@ -1751,6 +1758,7 @@ static CVReturn displayLinkOutputCallback(CVDisplayLinkRef displayLink, const CV short wheelDelta = [event deltaY]; vulkanExample->camera.translate(glm::vec3(0.0f, 0.0f, -(float)wheelDelta * 0.05f * vulkanExample->camera.movementSpeed)); + vulkanExample->viewUpdated = true; } // SRS - Window resizing already handled by windowResize() in VulkanExampleBase::submitFrame() diff --git a/base/vulkanexamplebase.h b/base/vulkanexamplebase.h index 6d5b28b8..03c5a2c9 100644 --- a/base/vulkanexamplebase.h +++ b/base/vulkanexamplebase.h @@ -96,7 +96,6 @@ class VulkanExampleBase { private: std::string getWindowTitle(); - bool viewUpdated = false; uint32_t destWidth; uint32_t destHeight; bool resizing = false; @@ -177,6 +176,7 @@ protected: public: bool prepared = false; bool resized = false; + bool viewUpdated = false; uint32_t width = 1280; uint32_t height = 720; diff --git a/xcode/MVKExample.cpp b/xcode/MVKExample.cpp index 3073d2d9..ab6acc53 100644 --- a/xcode/MVKExample.cpp +++ b/xcode/MVKExample.cpp @@ -107,6 +107,7 @@ void MVKExample::mouseDragged(double x, double y) { void MVKExample::scrollWheel(short wheelDelta) { _vulkanExample->camera.translate(glm::vec3(0.0f, 0.0f, wheelDelta * 0.05f * _vulkanExample->camera.movementSpeed)); + _vulkanExample->viewUpdated = true; } void MVKExample::fullScreen(bool fullscreen) { From bb4281ac24eff5a31b8dd4fe8ca15c0be4de649d Mon Sep 17 00:00:00 2001 From: Stephen Saunders Date: Fri, 8 Jul 2022 15:17:56 -0400 Subject: [PATCH 21/36] Update VK_KHR_portability_subset + VK_KHR_portability_enumeration implementations for iOS/macOS support with runtime checks --- base/VulkanDevice.cpp | 14 +++----------- base/vulkanexamplebase.cpp | 37 +++++++++++-------------------------- 2 files changed, 14 insertions(+), 37 deletions(-) diff --git a/base/VulkanDevice.cpp b/base/VulkanDevice.cpp index 9208be7b..1b20febf 100644 --- a/base/VulkanDevice.cpp +++ b/base/VulkanDevice.cpp @@ -9,16 +9,12 @@ */ #if (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK)) -// SRS - This is needed to make visible VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME +// SRS - Enable beta extensions and make VK_KHR_portability_subset visible #define VK_ENABLE_BETA_EXTENSIONS #endif #include #include -#if defined(VK_USE_PLATFORM_MACOS_MVK) && (VK_HEADER_VERSION >= 216) -#include -#endif - namespace vks { /** @@ -257,10 +253,6 @@ namespace vks deviceExtensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME); } -#if defined(VK_USE_PLATFORM_MACOS_MVK) && (VK_HEADER_VERSION >= 216) - deviceExtensions.push_back(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME); -#endif - VkDeviceCreateInfo deviceCreateInfo = {}; deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; deviceCreateInfo.queueCreateInfoCount = static_cast(queueCreateInfos.size());; @@ -284,8 +276,8 @@ namespace vks enableDebugMarkers = true; } -#if (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK)) - // SRS - When running on iOS/macOS with MoltenVK, must enable the VK_KHR_portability_subset device extension +#if (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK)) && defined(VK_KHR_portability_subset) + // SRS - When running on iOS/macOS with MoltenVK and VK_KHR_portability_subset is defined and supported by the device, enable the extension if (extensionSupported(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME)) { deviceExtensions.push_back(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME); diff --git a/base/vulkanexamplebase.cpp b/base/vulkanexamplebase.cpp index 2c2d350b..670b2e8d 100644 --- a/base/vulkanexamplebase.cpp +++ b/base/vulkanexamplebase.cpp @@ -55,19 +55,6 @@ VkResult VulkanExampleBase::createInstance(bool enableValidation) instanceExtensions.push_back(VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME); #endif -#if (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK)) - // SRS - When running on iOS/macOS with MoltenVK, enable VkPhysicalDeviceFeatures2 if not already enabled (required by VK_KHR_portability_subset) - if (std::find(enabledInstanceExtensions.begin(), enabledInstanceExtensions.end(), VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME) == enabledInstanceExtensions.end()) - { - enabledInstanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } -#endif - -#if defined(VK_USE_PLATFORM_MACOS_MVK) && (VK_HEADER_VERSION >= 216) - instanceExtensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME); - instanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); -#endif - // Get extensions supported by the instance and store for later use uint32_t extCount = 0; vkEnumerateInstanceExtensionProperties(nullptr, &extCount, nullptr); @@ -83,11 +70,11 @@ VkResult VulkanExampleBase::createInstance(bool enableValidation) } } -#if defined(VK_KHR_portability_enumeration) - // SRS - When VK_KHR_portability_enumeration is defined and supported, enable it to properly enumerate the physical device - if (std::find(supportedInstanceExtensions.begin(), supportedInstanceExtensions.end(), VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME) != supportedInstanceExtensions.end()) +#if (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK)) + // SRS - When running on iOS/macOS with MoltenVK, enable VK_KHR_get_physical_device_properties2 if not already enabled by the example (required by VK_KHR_portability_subset) + if (std::find(enabledInstanceExtensions.begin(), enabledInstanceExtensions.end(), VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME) == enabledInstanceExtensions.end()) { - enabledInstanceExtensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME); + enabledInstanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); } #endif @@ -110,8 +97,13 @@ VkResult VulkanExampleBase::createInstance(bool enableValidation) instanceCreateInfo.pNext = NULL; instanceCreateInfo.pApplicationInfo = &appInfo; -#if defined(VK_USE_PLATFORM_MACOS_MVK) && (VK_HEADER_VERSION >= 216) - instanceCreateInfo.flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; +#if (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK)) && defined(VK_KHR_portability_enumeration) + // SRS - When running on iOS/macOS with MoltenVK and VK_KHR_portability_enumeration is defined and supported by the instance, enable the extension and the flag + if (std::find(supportedInstanceExtensions.begin(), supportedInstanceExtensions.end(), VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME) != supportedInstanceExtensions.end()) + { + instanceExtensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME); + instanceCreateInfo.flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; + } #endif if (instanceExtensions.size() > 0) @@ -124,13 +116,6 @@ VkResult VulkanExampleBase::createInstance(bool enableValidation) instanceCreateInfo.enabledExtensionCount = (uint32_t)instanceExtensions.size(); instanceCreateInfo.ppEnabledExtensionNames = instanceExtensions.data(); } -#if defined(VK_KHR_portability_enumeration) - // SRS - When VK_KHR_portability_enumeration is defined and enabled, the VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR flag must be set - if (std::find(instanceExtensions.begin(), instanceExtensions.end(), VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME) != instanceExtensions.end()) - { - instanceCreateInfo.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; - } -#endif // The VK_LAYER_KHRONOS_validation contains all current validation functionality. // Note that on Android this layer requires at least NDK r20 From d9d3e8c1fbb56b8dcf652f514ef2601abe4e6b57 Mon Sep 17 00:00:00 2001 From: Stephen Saunders Date: Tue, 12 Jul 2022 18:46:39 -0400 Subject: [PATCH 22/36] ImGui example now shows Vulkan API and driver info, ImGui+TextOverlay+ConditionalRender+gltfSceneRendering examples now support macOS retina displays --- base/VulkanUIOverlay.cpp | 7 ++-- .../conditionalrender/conditionalrender.cpp | 4 +-- .../gltfscenerendering/gltfscenerendering.cpp | 2 +- examples/imgui/main.cpp | 36 ++++++++++++++++--- examples/textoverlay/textoverlay.cpp | 22 +++++++----- 5 files changed, 52 insertions(+), 19 deletions(-) diff --git a/base/VulkanUIOverlay.cpp b/base/VulkanUIOverlay.cpp index 65e7c7b7..96a6307b 100644 --- a/base/VulkanUIOverlay.cpp +++ b/base/VulkanUIOverlay.cpp @@ -79,12 +79,14 @@ namespace vks #else const std::string filename = getAssetPath() + "Roboto-Medium.ttf"; io.Fonts->AddFontFromFileTTF(filename.c_str(), 16.0f * scale); - ImGuiStyle& style = ImGui::GetStyle(); - style.ScaleAllSizes(scale); #endif io.Fonts->GetTexDataAsRGBA32(&fontData, &texWidth, &texHeight); VkDeviceSize uploadSize = texWidth*texHeight * 4 * sizeof(char); + //SRS - Set ImGui style scale factor to handle retina and other HiDPI displays (same as font scaling above) + ImGuiStyle& style = ImGui::GetStyle(); + style.ScaleAllSizes(scale); + // Create target image for copy VkImageCreateInfo imageInfo = vks::initializers::imageCreateInfo(); imageInfo.imageType = VK_IMAGE_TYPE_2D; @@ -324,7 +326,6 @@ namespace vks } // Index buffer - VkDeviceSize indexSize = imDrawData->TotalIdxCount * sizeof(ImDrawIdx); if ((indexBuffer.buffer == VK_NULL_HANDLE) || (indexCount < imDrawData->TotalIdxCount)) { indexBuffer.unmap(); indexBuffer.destroy(); diff --git a/examples/conditionalrender/conditionalrender.cpp b/examples/conditionalrender/conditionalrender.cpp index 5b3613b5..61790206 100644 --- a/examples/conditionalrender/conditionalrender.cpp +++ b/examples/conditionalrender/conditionalrender.cpp @@ -354,7 +354,7 @@ public: } ImGui::NewLine(); - ImGui::BeginChild("InnerRegion", ImVec2(200.0f, 400.0f), false); + ImGui::BeginChild("InnerRegion", ImVec2(200.0f * overlay->scale, 400.0f * overlay->scale), false); for (auto node : scene.linearNodes) { // Add visibility toggle checkboxes for all model nodes with a mesh if (node->mesh) { @@ -370,4 +370,4 @@ public: }; -VULKAN_EXAMPLE_MAIN() \ No newline at end of file +VULKAN_EXAMPLE_MAIN() diff --git a/examples/gltfscenerendering/gltfscenerendering.cpp b/examples/gltfscenerendering/gltfscenerendering.cpp index 8493c343..9090317a 100644 --- a/examples/gltfscenerendering/gltfscenerendering.cpp +++ b/examples/gltfscenerendering/gltfscenerendering.cpp @@ -652,7 +652,7 @@ void VulkanExample::OnUpdateUIOverlay(vks::UIOverlay* overlay) ImGui::NewLine(); // POI: Create a list of glTF nodes for visibility toggle - ImGui::BeginChild("#nodelist", ImVec2(0.0f, ImGui::GetTextLineHeightWithSpacing() * (glTFScene.nodes.size() + 4)), false); + ImGui::BeginChild("#nodelist", ImVec2(200.0f * overlay->scale, 340.0f * overlay->scale), false); for (auto &node : glTFScene.nodes) { if (overlay->checkBox(node.name.c_str(), &node.visible)) diff --git a/examples/imgui/main.cpp b/examples/imgui/main.cpp index 3f5f4382..cc802759 100644 --- a/examples/imgui/main.cpp +++ b/examples/imgui/main.cpp @@ -45,6 +45,7 @@ private: VkDescriptorSetLayout descriptorSetLayout; VkDescriptorSet descriptorSet; vks::VulkanDevice *device; + VkPhysicalDeviceDriverProperties driverProperties = {}; VulkanExampleBase *example; public: // UI params are set via push constants @@ -57,6 +58,12 @@ public: { device = example->vulkanDevice; ImGui::CreateContext(); + + //SRS - Set ImGui font and style scale factors to handle retina and other HiDPI displays + ImGuiIO& io = ImGui::GetIO(); + io.FontGlobalScale = example->UIOverlay.scale; + ImGuiStyle& style = ImGui::GetStyle(); + style.ScaleAllSizes(example->UIOverlay.scale); }; ~ImGUI() @@ -103,6 +110,16 @@ public: io.Fonts->GetTexDataAsRGBA32(&fontData, &texWidth, &texHeight); VkDeviceSize uploadSize = texWidth*texHeight * 4 * sizeof(char); + //SRS - Get Vulkan device driver information if available, use later for display + if (device->extensionSupported(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME)) + { + VkPhysicalDeviceProperties2 deviceProperties2 = {}; + deviceProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; + deviceProperties2.pNext = &driverProperties; + driverProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES; + vkGetPhysicalDeviceProperties2(device->physicalDevice, &deviceProperties2); + } + // Create target image for copy VkImageCreateInfo imageInfo = vks::initializers::imageCreateInfo(); imageInfo.imageType = VK_IMAGE_TYPE_2D; @@ -325,10 +342,15 @@ public: // Init imGui windows and elements - ImVec4 clear_color = ImColor(114, 144, 154); - static float f = 0.0f; + // SRS - Set initial position of default Debug window (note: Debug window sets its own initial size, use ImGuiSetCond_Always to override) + ImGui::SetWindowPos(ImVec2(20 * example->UIOverlay.scale, 20 * example->UIOverlay.scale), ImGuiSetCond_FirstUseEver); + ImGui::SetWindowSize(ImVec2(300 * example->UIOverlay.scale, 300 * example->UIOverlay.scale), ImGuiSetCond_Always); ImGui::TextUnformatted(example->title.c_str()); ImGui::TextUnformatted(device->properties.deviceName); + + //SRS - Display Vulkan API version and device driver information if available (otherwise blank) + ImGui::Text("Vulkan API %i.%i.%i", VK_API_VERSION_MAJOR(device->properties.apiVersion), VK_API_VERSION_MINOR(device->properties.apiVersion), VK_API_VERSION_PATCH(device->properties.apiVersion)); + ImGui::Text("%s %s", driverProperties.driverName, driverProperties.driverInfo); // Update frame time display if (updateFrameGraph) { @@ -349,7 +371,9 @@ public: ImGui::InputFloat3("position", &example->camera.position.x, 2); ImGui::InputFloat3("rotation", &example->camera.rotation.x, 2); - ImGui::SetNextWindowSize(ImVec2(200, 200), ImGuiSetCond_FirstUseEver); + // SRS - Set initial position and size of Example settings window + ImGui::SetNextWindowPos(ImVec2(20 * example->UIOverlay.scale, 360 * example->UIOverlay.scale), ImGuiSetCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(300 * example->UIOverlay.scale, 200 * example->UIOverlay.scale), ImGuiSetCond_FirstUseEver); ImGui::Begin("Example settings"); ImGui::Checkbox("Render models", &uiSettings.displayModels); ImGui::Checkbox("Display logos", &uiSettings.displayLogos); @@ -358,7 +382,7 @@ public: ImGui::SliderFloat("Light speed", &uiSettings.lightSpeed, 0.1f, 1.0f); ImGui::End(); - ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiSetCond_FirstUseEver); + //SRS - ShowDemoWindow() sets its own initial position and size, cannot override here ImGui::ShowDemoWindow(); // Render to generate draw buffers @@ -499,6 +523,10 @@ public: camera.setPosition(glm::vec3(0.0f, 0.0f, -4.8f)); camera.setRotation(glm::vec3(4.5f, -380.0f, 0.0f)); camera.setPerspective(45.0f, (float)width / (float)height, 0.1f, 256.0f); + + //SRS - Enable VK_KHR_get_physical_device_properties2 to retrieve device driver information for display + enabledInstanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); + // Don't use the ImGui overlay of the base framework in this sample settings.overlay = false; } diff --git a/examples/textoverlay/textoverlay.cpp b/examples/textoverlay/textoverlay.cpp index 4c8fa1e4..2ac70714 100644 --- a/examples/textoverlay/textoverlay.cpp +++ b/examples/textoverlay/textoverlay.cpp @@ -31,6 +31,7 @@ private: uint32_t *frameBufferWidth; uint32_t *frameBufferHeight; + float scale; VkSampler sampler; VkImage image; @@ -70,6 +71,7 @@ public: VkFormat depthformat, uint32_t *framebufferwidth, uint32_t *framebufferheight, + float scale, std::vector shaderstages) { this->vulkanDevice = vulkanDevice; @@ -87,6 +89,7 @@ public: this->frameBufferWidth = framebufferwidth; this->frameBufferHeight = framebufferheight; + this->scale = scale; cmdBuffers.resize(framebuffers.size()); prepareResources(); @@ -490,8 +493,8 @@ public: assert(mapped != nullptr); - const float charW = 1.5f / *frameBufferWidth; - const float charH = 1.5f / *frameBufferHeight; + const float charW = 1.5f * scale / *frameBufferWidth; + const float charH = 1.5f * scale / *frameBufferHeight; float fbW = (float)*frameBufferWidth; float fbH = (float)*frameBufferHeight; @@ -700,23 +703,23 @@ public: { textOverlay->beginTextUpdate(); - textOverlay->addText(title, 5.0f, 5.0f, TextOverlay::alignLeft); + textOverlay->addText(title, 5.0f * UIOverlay.scale, 5.0f * UIOverlay.scale, TextOverlay::alignLeft); std::stringstream ss; ss << std::fixed << std::setprecision(2) << (frameTimer * 1000.0f) << "ms (" << lastFPS << " fps)"; - textOverlay->addText(ss.str(), 5.0f, 25.0f, TextOverlay::alignLeft); + textOverlay->addText(ss.str(), 5.0f * UIOverlay.scale, 25.0f * UIOverlay.scale, TextOverlay::alignLeft); - textOverlay->addText(deviceProperties.deviceName, 5.0f, 45.0f, TextOverlay::alignLeft); + textOverlay->addText(deviceProperties.deviceName, 5.0f * UIOverlay.scale, 45.0f * UIOverlay.scale, TextOverlay::alignLeft); // Display current model view matrix - textOverlay->addText("model view matrix", (float)width, 5.0f, TextOverlay::alignRight); + textOverlay->addText("model view matrix", (float)width - 5.0f * UIOverlay.scale, 5.0f * UIOverlay.scale, TextOverlay::alignRight); for (uint32_t i = 0; i < 4; i++) { ss.str(""); ss << std::fixed << std::setprecision(2) << std::showpos; ss << uboVS.modelView[0][i] << " " << uboVS.modelView[1][i] << " " << uboVS.modelView[2][i] << " " << uboVS.modelView[3][i]; - textOverlay->addText(ss.str(), (float)width, 25.0f + (float)i * 20.0f, TextOverlay::alignRight); + textOverlay->addText(ss.str(), (float)width - 5.0f * UIOverlay.scale, (25.0f + (float)i * 20.0f) * UIOverlay.scale, TextOverlay::alignRight); } glm::vec3 projected = glm::project(glm::vec3(0.0f), uboVS.modelView, uboVS.projection, glm::vec4(0, 0, (float)width, (float)height)); @@ -724,8 +727,8 @@ public: #if defined(__ANDROID__) #else - textOverlay->addText("Press \"space\" to toggle text overlay", 5.0f, 65.0f, TextOverlay::alignLeft); - textOverlay->addText("Hold middle mouse button and drag to move", 5.0f, 85.0f, TextOverlay::alignLeft); + textOverlay->addText("Press \"space\" to toggle text overlay", 5.0f * UIOverlay.scale, 65.0f * UIOverlay.scale, TextOverlay::alignLeft); + textOverlay->addText("Hold middle mouse button and drag to move", 5.0f * UIOverlay.scale, 85.0f * UIOverlay.scale, TextOverlay::alignLeft); #endif textOverlay->endTextUpdate(); } @@ -842,6 +845,7 @@ public: depthFormat, &width, &height, + UIOverlay.scale, shaderStages ); updateTextOverlay(); From 7f5aa150d6d53f032f27411872a04a155e57b5aa Mon Sep 17 00:00:00 2001 From: Stephen Saunders Date: Fri, 15 Jul 2022 10:33:57 -0400 Subject: [PATCH 23/36] Update benchmark-all.py script to include current examples and support macOS --- bin/benchmark-all.py | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/bin/benchmark-all.py b/bin/benchmark-all.py index 78773df2..2bb6fe43 100644 --- a/bin/benchmark-all.py +++ b/bin/benchmark-all.py @@ -10,38 +10,57 @@ EXAMPLES = [ "computecullandlod", "computenbody", "computeparticles", + "computeraytracing", "computeshader", + "conditionalrender", + "conservativeraster", "debugmarker", "deferred", "deferredmultisampling", "deferredshadows", + "descriptorindexing", + "descriptorsets", "displacement", "distancefieldfonts", + "dynamicrendering", "dynamicuniformbuffer", "gears", "geometryshader", + "gltfloading", + "gltfscenerendering", + "gltfskinning", + "graphicspipelinelibrary", "hdr", "imgui", "indirectdraw", + "inlineuniformblocks", + "inputattachments", "instancing", - "mesh", "multisampling", "multithreading", + "multiview", + "negativeviewportheight", "occlusionquery", "offscreen", + "oit", "parallaxmapping", "particlefire", "pbrbasic", "pbribl", "pbrtexture", "pipelines", + "pipelinestatistics", "pushconstants", + "pushdescriptors", "radialblur", - "raytracing", - "scenerendering", + "rayquery", + "raytracingbasic", + "raytracingcallable", + "raytracingreflections", + "raytracingshadows", "shadowmapping", + "shadowmappingcascade", "shadowmappingomni", - "skeletalanimation", "specializationconstants", "sphericalenvmapping", "ssao", @@ -54,9 +73,12 @@ EXAMPLES = [ "texture3d", "texturearray", "texturecubemap", + "texturecubemaparray", "texturemipmapgen", "texturesparseresidency", "triangle", + "variablerateshading", + "vertexattributes", "viewportarray", "vulkanscene" ] @@ -71,7 +93,7 @@ os.makedirs("./benchmark", exist_ok=True) for example in EXAMPLES: print("---- (%d/%d) Running %s in benchmark mode ----" % (CURR_INDEX+1, len(EXAMPLES), example)) - if platform.system() == 'Linux': + if platform.system() == 'Linux' or platform.system() == 'Darwin': RESULT_CODE = subprocess.call("./%s %s -bf ./benchmark/%s.csv 5" % (example, ARGS, example), shell=True) else: RESULT_CODE = subprocess.call("%s %s -bf ./benchmark/%s.csv 5" % (example, ARGS, example)) From 46b2027dd19ea0bee2d1f369b8b697841c28314a Mon Sep 17 00:00:00 2001 From: Stephen Saunders Date: Tue, 19 Jul 2022 09:59:48 -0400 Subject: [PATCH 24/36] Handle Vulkan / memory cleanup on shutdown for macOS benchmarking case --- base/vulkanexamplebase.h | 1 + examples/triangle/triangle.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/base/vulkanexamplebase.h b/base/vulkanexamplebase.h index 03c5a2c9..9f814cf9 100644 --- a/base/vulkanexamplebase.h +++ b/base/vulkanexamplebase.h @@ -536,6 +536,7 @@ int main(const int argc, const char *argv[]) \ vulkanExample->setupWindow(nullptr); \ vulkanExample->prepare(); \ vulkanExample->renderLoop(); \ + delete(vulkanExample); \ } \ return 0; \ } diff --git a/examples/triangle/triangle.cpp b/examples/triangle/triangle.cpp index 6d0e35d3..694cd8be 100644 --- a/examples/triangle/triangle.cpp +++ b/examples/triangle/triangle.cpp @@ -1259,7 +1259,7 @@ int main(const int argc, const char *argv[]) vulkanExample->setupWindow(nullptr); vulkanExample->prepare(); vulkanExample->renderLoop(); - //delete(vulkanExample); // SRS - vulkanExample deleted by AppDelegate termination event handler + delete(vulkanExample); // SRS - handle benchmarking case, normally deleted by applicationWillTerminate() event handler } return 0; } From c89d4eb7760264d7a7d771707185d8ca337e385e Mon Sep 17 00:00:00 2001 From: Stephen Saunders Date: Wed, 27 Jul 2022 01:11:20 -0400 Subject: [PATCH 25/36] Code Review: a) revert TinyGLTF #defines, b) call vkDeviceWaitIdle() in macOS/iOS termination handlers, c) remove OpenMP target_compile_options() in CMakeLists --- base/vulkanexamplebase.cpp | 3 ++- examples/CMakeLists.txt | 12 ++++-------- examples/computeraytracing/computeraytracing.cpp | 3 --- examples/gltfscenerendering/gltfscenerendering.h | 2 +- examples/triangle/triangle.cpp | 3 --- examples/vertexattributes/vertexattributes.h | 2 +- xcode/MVKExample.cpp | 3 ++- 7 files changed, 10 insertions(+), 18 deletions(-) diff --git a/base/vulkanexamplebase.cpp b/base/vulkanexamplebase.cpp index 670b2e8d..2b12eaab 100644 --- a/base/vulkanexamplebase.cpp +++ b/base/vulkanexamplebase.cpp @@ -1556,7 +1556,8 @@ dispatch_group_t concurrentGroup; { vulkanExample->quit = YES; dispatch_group_wait(concurrentGroup, DISPATCH_TIME_FOREVER); - delete vulkanExample; + vkDeviceWaitIdle(vulkanExample->vulkanDevice->logicalDevice); + delete(vulkanExample); } @end diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 7fa6373c..e8a04ae2 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -59,15 +59,11 @@ function(buildExample EXAMPLE_NAME) endif(WIN32) set_target_properties(${EXAMPLE_NAME} PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) - #if(OpenMP_CXX_FOUND) - # SRS - target_compile_options is not needed when using target_link_libraries( OpenMP::OpenMP_CXX) syntax below - #target_compile_options(${EXAMPLE_NAME} PRIVATE ${OpenMP_CXX_FLAGS}) - IF(${EXAMPLE_NAME} STREQUAL "texture3d") - if(OpenMP_CXX_FOUND) - target_link_libraries(${EXAMPLE_NAME} OpenMP::OpenMP_CXX) - endif() + if(${EXAMPLE_NAME} STREQUAL "texture3d") + if(OpenMP_CXX_FOUND) + target_link_libraries(${EXAMPLE_NAME} OpenMP::OpenMP_CXX) endif() - #endif() + endif() if(RESOURCE_INSTALL_DIR) install(TARGETS ${EXAMPLE_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/examples/computeraytracing/computeraytracing.cpp b/examples/computeraytracing/computeraytracing.cpp index e857d1cd..6cb83490 100644 --- a/examples/computeraytracing/computeraytracing.cpp +++ b/examples/computeraytracing/computeraytracing.cpp @@ -94,9 +94,6 @@ public: ~VulkanExample() { - // SRS - Ensure all operations on the device have finished before destroying resources - vkDeviceWaitIdle(device); - // Graphics vkDestroyPipeline(device, graphics.pipeline, nullptr); vkDestroyPipelineLayout(device, graphics.pipelineLayout, nullptr); diff --git a/examples/gltfscenerendering/gltfscenerendering.h b/examples/gltfscenerendering/gltfscenerendering.h index 1d6cffe3..1e1d673c 100644 --- a/examples/gltfscenerendering/gltfscenerendering.h +++ b/examples/gltfscenerendering/gltfscenerendering.h @@ -15,7 +15,7 @@ #define TINYGLTF_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION #define TINYGLTF_NO_STB_IMAGE_WRITE -//#define TINYGLTF_NO_STB_IMAGE // SRS - Comment out to enable default image loader, otherwise LoadImageData() is undefined +#define TINYGLTF_NO_STB_IMAGE #define TINYGLTF_NO_EXTERNAL_IMAGE #ifdef VK_USE_PLATFORM_ANDROID_KHR #define TINYGLTF_ANDROID_LOAD_FROM_ASSETS diff --git a/examples/triangle/triangle.cpp b/examples/triangle/triangle.cpp index 694cd8be..fc775197 100644 --- a/examples/triangle/triangle.cpp +++ b/examples/triangle/triangle.cpp @@ -126,9 +126,6 @@ public: ~VulkanExample() { - // SRS - Ensure all operations on the device have finished before destroying resources - vkDeviceWaitIdle(device); - // Clean up used Vulkan resources // Note: Inherited destructor cleans up resources stored in base class vkDestroyPipeline(device, pipeline, nullptr); diff --git a/examples/vertexattributes/vertexattributes.h b/examples/vertexattributes/vertexattributes.h index d51f96ec..1630ee5d 100644 --- a/examples/vertexattributes/vertexattributes.h +++ b/examples/vertexattributes/vertexattributes.h @@ -9,7 +9,7 @@ #define TINYGLTF_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION #define TINYGLTF_NO_STB_IMAGE_WRITE -//#define TINYGLTF_NO_STB_IMAGE // SRS - Comment out to enable default image loader, otherwise LoadImageData() is undefined +#define TINYGLTF_NO_STB_IMAGE #define TINYGLTF_NO_EXTERNAL_IMAGE #ifdef VK_USE_PLATFORM_ANDROID_KHR #define TINYGLTF_ANDROID_LOAD_FROM_ASSETS diff --git a/xcode/MVKExample.cpp b/xcode/MVKExample.cpp index ab6acc53..82488305 100644 --- a/xcode/MVKExample.cpp +++ b/xcode/MVKExample.cpp @@ -125,5 +125,6 @@ MVKExample::MVKExample(void* view, double scaleUI) { } MVKExample::~MVKExample() { - delete _vulkanExample; + vkDeviceWaitIdle(_vulkanExample->vulkanDevice->logicalDevice); + delete(_vulkanExample); } From 6ef16905ce32ff9c381eddc4ed2a65b504d382c1 Mon Sep 17 00:00:00 2001 From: Stephen Saunders Date: Wed, 27 Jul 2022 13:43:52 -0400 Subject: [PATCH 26/36] Headless examples: update validation layer name & implement macOS VK_KHR_portability_subset / VK_KHR_portability_enumeration --- examples/computeheadless/computeheadless.cpp | 62 ++++++++++++++++++-- examples/renderheadless/renderheadless.cpp | 62 ++++++++++++++++++-- 2 files changed, 114 insertions(+), 10 deletions(-) diff --git a/examples/computeheadless/computeheadless.cpp b/examples/computeheadless/computeheadless.cpp index 5095222d..d11a2235 100644 --- a/examples/computeheadless/computeheadless.cpp +++ b/examples/computeheadless/computeheadless.cpp @@ -26,6 +26,9 @@ #include #include +#if defined(VK_USE_PLATFORM_MACOS_MVK) +#define VK_ENABLE_BETA_EXTENSIONS +#endif #include #include "VulkanTools.h" @@ -145,9 +148,10 @@ public: const char* validationLayers[] = { "VK_LAYER_GOOGLE_threading", "VK_LAYER_LUNARG_parameter_validation", "VK_LAYER_LUNARG_object_tracker","VK_LAYER_LUNARG_core_validation", "VK_LAYER_LUNARG_swapchain", "VK_LAYER_GOOGLE_unique_objects" }; layerCount = 6; #else - const char* validationLayers[] = { "VK_LAYER_LUNARG_standard_validation" }; + const char* validationLayers[] = { "VK_LAYER_KHRONOS_validation" }; layerCount = 1; #endif + std::vector instanceExtensions = {}; #if DEBUG // Check if layers are available uint32_t instanceLayerCount; @@ -170,14 +174,39 @@ public: } } - const char *validationExt = VK_EXT_DEBUG_REPORT_EXTENSION_NAME; if (layersAvailable) { + instanceExtensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME); instanceCreateInfo.ppEnabledLayerNames = validationLayers; instanceCreateInfo.enabledLayerCount = layerCount; - instanceCreateInfo.enabledExtensionCount = 1; - instanceCreateInfo.ppEnabledExtensionNames = &validationExt; } #endif +#if defined(VK_USE_PLATFORM_MACOS_MVK) + // SRS - When running on macOS with MoltenVK, enable VK_KHR_get_physical_device_properties2 (required by VK_KHR_portability_subset) + instanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); +#if defined(VK_KHR_portability_enumeration) + // SRS - When running on macOS with MoltenVK and VK_KHR_portability_enumeration is defined and supported by the instance, enable the extension and the flag + uint32_t instanceExtCount = 0; + vkEnumerateInstanceExtensionProperties(nullptr, &instanceExtCount, nullptr); + if (instanceExtCount > 0) + { + std::vector extensions(instanceExtCount); + if (vkEnumerateInstanceExtensionProperties(nullptr, &instanceExtCount, &extensions.front()) == VK_SUCCESS) + { + for (VkExtensionProperties extension : extensions) + { + if (strcmp(extension.extensionName, VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME) == 0) + { + instanceExtensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME); + instanceCreateInfo.flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; + break; + } + } + } + } +#endif +#endif + instanceCreateInfo.enabledExtensionCount = (uint32_t)instanceExtensions.size(); + instanceCreateInfo.ppEnabledExtensionNames = instanceExtensions.data(); VK_CHECK_RESULT(vkCreateInstance(&instanceCreateInfo, nullptr, &instance)); #if defined(VK_USE_PLATFORM_ANDROID_KHR) @@ -233,6 +262,29 @@ public: deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; deviceCreateInfo.queueCreateInfoCount = 1; deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo; + std::vector deviceExtensions = {}; +#if defined(VK_USE_PLATFORM_MACOS_MVK) && defined(VK_KHR_portability_subset) + // SRS - When running on macOS with MoltenVK and VK_KHR_portability_subset is defined and supported by the device, enable the extension + uint32_t deviceExtCount = 0; + vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &deviceExtCount, nullptr); + if (deviceExtCount > 0) + { + std::vector extensions(deviceExtCount); + if (vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &deviceExtCount, &extensions.front()) == VK_SUCCESS) + { + for (VkExtensionProperties extension : extensions) + { + if (strcmp(extension.extensionName, VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME) == 0) + { + deviceExtensions.push_back(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME); + break; + } + } + } + } +#endif + deviceCreateInfo.enabledExtensionCount = (uint32_t)deviceExtensions.size(); + deviceCreateInfo.ppEnabledExtensionNames = deviceExtensions.data(); VK_CHECK_RESULT(vkCreateDevice(physicalDevice, &deviceCreateInfo, nullptr, &device)); // Get a compute queue @@ -562,4 +614,4 @@ int main() { delete(vulkanExample); return 0; } -#endif \ No newline at end of file +#endif diff --git a/examples/renderheadless/renderheadless.cpp b/examples/renderheadless/renderheadless.cpp index ba41bf8a..592d1340 100644 --- a/examples/renderheadless/renderheadless.cpp +++ b/examples/renderheadless/renderheadless.cpp @@ -30,6 +30,9 @@ #include #include +#if defined(VK_USE_PLATFORM_MACOS_MVK) +#define VK_ENABLE_BETA_EXTENSIONS +#endif #include #include "VulkanTools.h" @@ -175,9 +178,10 @@ public: const char* validationLayers[] = { "VK_LAYER_GOOGLE_threading", "VK_LAYER_LUNARG_parameter_validation", "VK_LAYER_LUNARG_object_tracker","VK_LAYER_LUNARG_core_validation", "VK_LAYER_LUNARG_swapchain", "VK_LAYER_GOOGLE_unique_objects" }; layerCount = 6; #else - const char* validationLayers[] = { "VK_LAYER_LUNARG_standard_validation" }; + const char* validationLayers[] = { "VK_LAYER_KHRONOS_validation" }; layerCount = 1; #endif + std::vector instanceExtensions = {}; #if DEBUG // Check if layers are available uint32_t instanceLayerCount; @@ -200,14 +204,39 @@ public: } } - const char *validationExt = VK_EXT_DEBUG_REPORT_EXTENSION_NAME; if (layersAvailable) { + instanceExtensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME); instanceCreateInfo.ppEnabledLayerNames = validationLayers; instanceCreateInfo.enabledLayerCount = layerCount; - instanceCreateInfo.enabledExtensionCount = 1; - instanceCreateInfo.ppEnabledExtensionNames = &validationExt; } #endif +#if defined(VK_USE_PLATFORM_MACOS_MVK) + // SRS - When running on macOS with MoltenVK, enable VK_KHR_get_physical_device_properties2 (required by VK_KHR_portability_subset) + instanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); +#if defined(VK_KHR_portability_enumeration) + // SRS - When running on macOS with MoltenVK and VK_KHR_portability_enumeration is defined and supported by the instance, enable the extension and the flag + uint32_t instanceExtCount = 0; + vkEnumerateInstanceExtensionProperties(nullptr, &instanceExtCount, nullptr); + if (instanceExtCount > 0) + { + std::vector extensions(instanceExtCount); + if (vkEnumerateInstanceExtensionProperties(nullptr, &instanceExtCount, &extensions.front()) == VK_SUCCESS) + { + for (VkExtensionProperties extension : extensions) + { + if (strcmp(extension.extensionName, VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME) == 0) + { + instanceExtensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME); + instanceCreateInfo.flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; + break; + } + } + } + } +#endif +#endif + instanceCreateInfo.enabledExtensionCount = (uint32_t)instanceExtensions.size(); + instanceCreateInfo.ppEnabledExtensionNames = instanceExtensions.data(); VK_CHECK_RESULT(vkCreateInstance(&instanceCreateInfo, nullptr, &instance)); #if defined(VK_USE_PLATFORM_ANDROID_KHR) @@ -262,6 +291,29 @@ public: deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; deviceCreateInfo.queueCreateInfoCount = 1; deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo; + std::vector deviceExtensions = {}; +#if defined(VK_USE_PLATFORM_MACOS_MVK) && defined(VK_KHR_portability_subset) + // SRS - When running on macOS with MoltenVK and VK_KHR_portability_subset is defined and supported by the device, enable the extension + uint32_t deviceExtCount = 0; + vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &deviceExtCount, nullptr); + if (deviceExtCount > 0) + { + std::vector extensions(deviceExtCount); + if (vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &deviceExtCount, &extensions.front()) == VK_SUCCESS) + { + for (VkExtensionProperties extension : extensions) + { + if (strcmp(extension.extensionName, VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME) == 0) + { + deviceExtensions.push_back(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME); + break; + } + } + } + } +#endif + deviceCreateInfo.enabledExtensionCount = (uint32_t)deviceExtensions.size(); + deviceCreateInfo.ppEnabledExtensionNames = deviceExtensions.data(); VK_CHECK_RESULT(vkCreateDevice(physicalDevice, &deviceCreateInfo, nullptr, &device)); // Get a graphics queue @@ -894,4 +946,4 @@ int main() { delete(vulkanExample); return 0; } -#endif \ No newline at end of file +#endif From 3066f15e1867bb007bb3357ef69a4578dbb98323 Mon Sep 17 00:00:00 2001 From: Sascha Willems Date: Sat, 30 Jul 2022 09:14:11 +0200 Subject: [PATCH 27/36] Bugfix for graphics pipeline library sample --- .../graphicspipelinelibrary.cpp | 68 ++++++++++++------- 1 file changed, 44 insertions(+), 24 deletions(-) diff --git a/examples/graphicspipelinelibrary/graphicspipelinelibrary.cpp b/examples/graphicspipelinelibrary/graphicspipelinelibrary.cpp index b15bc245..39886aa3 100644 --- a/examples/graphicspipelinelibrary/graphicspipelinelibrary.cpp +++ b/examples/graphicspipelinelibrary/graphicspipelinelibrary.cpp @@ -16,6 +16,8 @@ class VulkanExample: public VulkanExampleBase { public: + bool linkTimeOptimization = true; + vkglTF::Model scene; struct UBOVS { @@ -35,6 +37,7 @@ public: VkPipeline vertexInputInterface; VkPipeline preRasterizationShaders; VkPipeline fragmentOutputInterface; + std::vector fragmentShaders; } pipelineLibrary; std::vector pipelines{}; @@ -80,6 +83,13 @@ public: for (auto pipeline : pipelines) { vkDestroyPipeline(device, pipeline, nullptr); } + for (auto pipeline : pipelineLibrary.fragmentShaders) { + vkDestroyPipeline(device, pipeline, nullptr); + } + vkDestroyPipeline(device, pipelineLibrary.fragmentOutputInterface, nullptr); + vkDestroyPipeline(device, pipelineLibrary.preRasterizationShaders, nullptr); + vkDestroyPipeline(device, pipelineLibrary.vertexInputInterface, nullptr); + vkDestroyPipelineCache(device, threadPipelineCache, nullptr); vkDestroyPipelineLayout(device, pipelineLayout, nullptr); vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); uniformBuffer.destroy(); @@ -238,14 +248,14 @@ public: VkPipelineVertexInputStateCreateInfo vertexInputState = *vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::Color }); VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); - VkGraphicsPipelineCreateInfo pipelineCI{}; - pipelineCI.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - pipelineCI.flags = VK_PIPELINE_CREATE_LIBRARY_BIT_KHR | VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT; - pipelineCI.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - pipelineCI.pNext = &libraryInfo; - pipelineCI.pInputAssemblyState = &inputAssemblyState; - pipelineCI.pVertexInputState = &vertexInputState; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelineLibrary.vertexInputInterface)); + VkGraphicsPipelineCreateInfo pipelineLibraryCI{}; + pipelineLibraryCI.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + pipelineLibraryCI.flags = VK_PIPELINE_CREATE_LIBRARY_BIT_KHR | VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT; + pipelineLibraryCI.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + pipelineLibraryCI.pNext = &libraryInfo; + pipelineLibraryCI.pInputAssemblyState = &inputAssemblyState; + pipelineLibraryCI.pVertexInputState = &vertexInputState; + VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineLibraryCI, nullptr, &pipelineLibrary.vertexInputInterface)); } // Creata a pipeline library for the vertex shader stage @@ -285,18 +295,18 @@ public: shaderStageCI.stage = VK_SHADER_STAGE_VERTEX_BIT; shaderStageCI.pName = "main"; - VkGraphicsPipelineCreateInfo pipelineCI{}; - pipelineCI.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - pipelineCI.pNext = &libraryInfo; - pipelineCI.renderPass = renderPass; - pipelineCI.flags = VK_PIPELINE_CREATE_LIBRARY_BIT_KHR | VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT; - pipelineCI.stageCount = 1; - pipelineCI.pStages = &shaderStageCI; - pipelineCI.layout = pipelineLayout; - pipelineCI.pDynamicState = &dynamicInfo; - pipelineCI.pViewportState = &viewportState; - pipelineCI.pRasterizationState = &rasterizationState; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipelineLibrary.preRasterizationShaders)); + VkGraphicsPipelineCreateInfo pipelineLibraryCI{}; + pipelineLibraryCI.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + pipelineLibraryCI.pNext = &libraryInfo; + pipelineLibraryCI.renderPass = renderPass; + pipelineLibraryCI.flags = VK_PIPELINE_CREATE_LIBRARY_BIT_KHR | VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT; + pipelineLibraryCI.stageCount = 1; + pipelineLibraryCI.pStages = &shaderStageCI; + pipelineLibraryCI.layout = pipelineLayout; + pipelineLibraryCI.pDynamicState = &dynamicInfo; + pipelineLibraryCI.pViewportState = &viewportState; + pipelineLibraryCI.pRasterizationState = &rasterizationState; + VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineLibraryCI, nullptr, &pipelineLibrary.preRasterizationShaders)); } // Create a pipeline library for the fragment output interface @@ -314,6 +324,7 @@ public: pipelineLibraryCI.pNext = &libraryInfo; pipelineLibraryCI.layout = pipelineLayout; pipelineLibraryCI.renderPass = renderPass; + pipelineLibraryCI.flags = VK_PIPELINE_CREATE_LIBRARY_BIT_KHR | VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT; pipelineLibraryCI.pColorBlendState = &colorBlendState; pipelineLibraryCI.pMultisampleState = &multisampleState; VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineLibraryCI, nullptr, &pipelineLibrary.fragmentOutputInterface)); @@ -393,15 +404,15 @@ public: pipelineCI.renderPass = renderPass; pipelineCI.pDepthStencilState = &depthStencilState; pipelineCI.pMultisampleState = &multisampleState; - VkPipeline fragment_shader = VK_NULL_HANDLE; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, threadPipelineCache, 1, &pipelineCI, nullptr, &fragment_shader)); + VkPipeline fragmentShader = VK_NULL_HANDLE; + VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, threadPipelineCache, 1, &pipelineCI, nullptr, &fragmentShader)); // Create the pipeline using the pre-built pipeline library parts // Except for above fragment shader part all parts have been pre-built and will be re-used std::vector libraries = { pipelineLibrary.vertexInputInterface, pipelineLibrary.preRasterizationShaders, - fragment_shader, + fragmentShader, pipelineLibrary.fragmentOutputInterface }; // Link the library parts into a graphics pipeline @@ -417,12 +428,20 @@ public: VkGraphicsPipelineCreateInfo executablePipelineCI{}; executablePipelineCI.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; executablePipelineCI.pNext = &pipelineLibraryCI; - executablePipelineCI.flags |= optimized ? VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT : 0; + executablePipelineCI.layout = pipelineLayout; + if (linkTimeOptimization) + { + // If link time optimization is activated in the UI, we set the VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT flag which will let the implementation do additional optimizations at link time + // This trades in pipeline creation time for run-time performance + executablePipelineCI.flags = VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT; + } VkPipeline executable = VK_NULL_HANDLE; VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, threadPipelineCache, 1, &executablePipelineCI, nullptr, &executable)); pipelines.push_back(executable); + // Push fragment shader to list for deletion in the sample's destructor + pipelineLibrary.fragmentShaders.push_back(fragmentShader); } // Prepare and initialize uniform buffer containing shader uniforms @@ -502,6 +521,7 @@ public: virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) { + overlay->checkBox("Link time optimization", &linkTimeOptimization); if (overlay->button("New pipeline")) { // Spwan a thread to create a new pipeline in the background std::thread pipelineGenerationThread(&VulkanExample::threadFn, this); From 05fa98f26bc8141ca537f6bac2666bec3d1c988d Mon Sep 17 00:00:00 2001 From: Sascha Willems Date: Sat, 30 Jul 2022 09:16:36 +0200 Subject: [PATCH 28/36] Change light pos --- examples/graphicspipelinelibrary/graphicspipelinelibrary.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/graphicspipelinelibrary/graphicspipelinelibrary.cpp b/examples/graphicspipelinelibrary/graphicspipelinelibrary.cpp index 39886aa3..79922a4f 100644 --- a/examples/graphicspipelinelibrary/graphicspipelinelibrary.cpp +++ b/examples/graphicspipelinelibrary/graphicspipelinelibrary.cpp @@ -23,7 +23,7 @@ public: struct UBOVS { glm::mat4 projection; glm::mat4 modelView; - glm::vec4 lightPos = glm::vec4(0.0f, 2.0f, 1.0f, 0.0f); + glm::vec4 lightPos = glm::vec4(0.0f, -2.0f, 1.0f, 0.0f); } uboVS; vks::Buffer uniformBuffer; From 5c2aaaf6931a8ab3610d7b25dbb588a448de190e Mon Sep 17 00:00:00 2001 From: Sascha Willems Date: Sat, 30 Jul 2022 09:27:50 +0200 Subject: [PATCH 29/36] Code cleanup Fixes #962 --- .../glsl/conservativeraster/fullscreen.frag | 2 +- .../glsl/conservativeraster/fullscreen.frag.spv | Bin 568 -> 568 bytes .../conservativeraster/conservativeraster.cpp | 7 ++----- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/data/shaders/glsl/conservativeraster/fullscreen.frag b/data/shaders/glsl/conservativeraster/fullscreen.frag index e5c1e497..b46ee0d3 100644 --- a/data/shaders/glsl/conservativeraster/fullscreen.frag +++ b/data/shaders/glsl/conservativeraster/fullscreen.frag @@ -1,6 +1,6 @@ #version 450 -layout (binding = 1) uniform sampler2D samplerColor; +layout (binding = 0) uniform sampler2D samplerColor; layout (location = 0) in vec2 inUV; layout (location = 0) out vec4 outFragColor; diff --git a/data/shaders/glsl/conservativeraster/fullscreen.frag.spv b/data/shaders/glsl/conservativeraster/fullscreen.frag.spv index 401a74346f9008f15c38c323804b7f38b18a3a12..a4aedf4a3dd434d9453601c41746b13066ad51c9 100644 GIT binary patch delta 23 ecmdnNvV(<_nMs+Qfq{{MYa-`!Muv?a-5CKkNd+hX delta 23 ecmdnNvV(<_nMs+Qfq{{MeIn;`M#haF-5CKkFa;(6 diff --git a/examples/conservativeraster/conservativeraster.cpp b/examples/conservativeraster/conservativeraster.cpp index 19cc838c..c2d7b518 100644 --- a/examples/conservativeraster/conservativeraster.cpp +++ b/examples/conservativeraster/conservativeraster.cpp @@ -478,8 +478,6 @@ public: // Scene rendering setLayoutBindings = { vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), // Binding 0: Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1), // Binding 1: Fragment shader image sampler - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT, 2) // Binding 2: Fragment shader uniform buffer }; descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings.data(), static_cast(setLayoutBindings.size())); VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayouts.scene)); @@ -488,8 +486,7 @@ public: // Fullscreen pass setLayoutBindings = { - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), // Binding 0: Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1) // Binding 1: Fragment shader image sampler + vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0) // Binding 0: Fragment shader image sampler }; descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings.data(), static_cast(setLayoutBindings.size())); VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayouts.fullscreen)); @@ -513,7 +510,7 @@ public: descriptorSetAllocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.fullscreen, 1); VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descriptorSetAllocInfo, &descriptorSets.fullscreen)); std::vector writeDescriptorSets = { - vks::initializers::writeDescriptorSet(descriptorSets.fullscreen, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &offscreenPass.descriptor), + vks::initializers::writeDescriptorSet(descriptorSets.fullscreen, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &offscreenPass.descriptor), }; vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); } From 1b3fe76cdb1820ac6de97d685f931366a1292784 Mon Sep 17 00:00:00 2001 From: Stephen Saunders Date: Mon, 1 Aug 2022 16:11:57 -0400 Subject: [PATCH 30/36] Fix F1 on/off toggle for ImGui overlay (all platforms), clean up keycode handling (mostly macOS/iOS) --- base/keycodes.hpp | 72 +++++++++++++--------- base/vulkanexamplebase.cpp | 71 ++++++++++++--------- examples/imgui/main.cpp | 11 ++-- examples/multithreading/multithreading.cpp | 4 +- examples/textoverlay/textoverlay.cpp | 2 - xcode/MVKExample.cpp | 5 ++ xcode/macos/DemoViewController.mm | 11 +++- 7 files changed, 106 insertions(+), 70 deletions(-) diff --git a/base/keycodes.hpp b/base/keycodes.hpp index 73f383ea..ca4fd5aa 100644 --- a/base/keycodes.hpp +++ b/base/keycodes.hpp @@ -40,16 +40,24 @@ #define GAMEPAD_BUTTON_START 0x1006 #define TOUCH_DOUBLE_TAP 0x1100 +// for textoverlay example +#define KEY_SPACE 0x3E // AKEYCODE_SPACE +#define KEY_KPADD 0x9D // AKEYCODE_NUMPAD_ADD + #elif (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK)) #if !defined(VK_EXAMPLE_XCODE_GENERATED) // For iOS and macOS pre-configured Xcode example project: Use character keycodes -// - Use numeric keys instead of function keys. +// - Use numeric keys as optional alternative to function keys #define KEY_DELETE 0x7F #define KEY_ESCAPE 0x1B -#define KEY_F1 '1' -#define KEY_F2 '2' -#define KEY_F3 '3' -#define KEY_F4 '4' +#define KEY_F1 0xF704 // NSF1FunctionKey +#define KEY_F2 0xF705 // NSF2FunctionKey +#define KEY_F3 0xF706 // NSF3FunctionKey +#define KEY_F4 0xF707 // NSF4FunctionKey +#define KEY_1 '1' +#define KEY_2 '2' +#define KEY_3 '3' +#define KEY_4 '4' #define KEY_W 'w' #define KEY_A 'a' #define KEY_S 's' @@ -69,32 +77,35 @@ #else // defined(VK_EXAMPLE_XCODE_GENERATED) // For cross-platform cmake-generated Xcode project: Use ANSI keyboard keycodes -// - Use numeric keys instead of function keys +// - Use numeric keys as optional alternative to function keys // - Use main keyboard plus/minus instead of keypad plus/minus -// Note: Carbon kVK_* definitions are used instead of these in vulkanexamplebase.cpp -// Currently only KEY_SPACE and KEY_KPADD are used in textoverlay.cpp example -#define KEY_DELETE 0x33 -#define KEY_ESCAPE 0x35 -#define KEY_F1 0x12 -#define KEY_F2 0x13 -#define KEY_F3 0x14 -#define KEY_F4 0x15 -#define KEY_W 0x0D -#define KEY_A 0x00 -#define KEY_S 0x01 -#define KEY_D 0x02 -#define KEY_P 0x23 -#define KEY_SPACE 0x31 -#define KEY_KPADD 0x18 -#define KEY_KPSUB 0x1B -#define KEY_B 0x0B -#define KEY_F 0x03 -#define KEY_L 0x25 -#define KEY_N 0x2D -#define KEY_O 0x1F -#define KEY_Q 0x0C -#define KEY_T 0x11 -#define KEY_Z 0x06 +#include +#define KEY_DELETE kVK_Delete +#define KEY_ESCAPE kVK_Escape +#define KEY_F1 kVK_F1 +#define KEY_F2 kVK_F2 +#define KEY_F3 kVK_F3 +#define KEY_F4 kVK_F4 +#define KEY_1 kVK_ANSI_1 +#define KEY_2 kVK_ANSI_2 +#define KEY_3 kVK_ANSI_3 +#define KEY_4 kVK_ANSI_4 +#define KEY_W kVK_ANSI_W +#define KEY_A kVK_ANSI_A +#define KEY_S kVK_ANSI_S +#define KEY_D kVK_ANSI_D +#define KEY_P kVK_ANSI_P +#define KEY_SPACE kVK_Space +#define KEY_KPADD kVK_ANSI_Equal +#define KEY_KPSUB kVK_ANSI_Minus +#define KEY_B kVK_ANSI_B +#define KEY_F kVK_ANSI_F +#define KEY_L kVK_ANSI_L +#define KEY_N kVK_ANSI_N +#define KEY_O kVK_ANSI_O +#define KEY_Q kVK_ANSI_Q +#define KEY_T kVK_ANSI_T +#define KEY_Z kVK_ANSI_Z #endif #elif defined(VK_USE_PLATFORM_DIRECTFB_EXT) @@ -122,6 +133,7 @@ #include // todo: hack for bloom example +#define KEY_ESCAPE KEY_ESC #define KEY_KPADD KEY_KPPLUS #define KEY_KPSUB KEY_KPMINUS diff --git a/base/vulkanexamplebase.cpp b/base/vulkanexamplebase.cpp index 2b12eaab..d30a94d9 100644 --- a/base/vulkanexamplebase.cpp +++ b/base/vulkanexamplebase.cpp @@ -10,7 +10,6 @@ #if (defined(VK_USE_PLATFORM_MACOS_MVK) && defined(VK_EXAMPLE_XCODE_GENERATED)) #include -#include #include #include #endif @@ -667,8 +666,9 @@ void VulkanExampleBase::updateOverlay() io.DeltaTime = frameTimer; io.MousePos = ImVec2(mousePos.x, mousePos.y); - io.MouseDown[0] = mouseButtons.left; - io.MouseDown[1] = mouseButtons.right; + io.MouseDown[0] = mouseButtons.left && UIOverlay.visible; + io.MouseDown[1] = mouseButtons.right && UIOverlay.visible; + io.MouseDown[2] = mouseButtons.middle && UIOverlay.visible; ImGui::NewFrame(); @@ -708,7 +708,7 @@ void VulkanExampleBase::updateOverlay() void VulkanExampleBase::drawUI(const VkCommandBuffer commandBuffer) { - if (settings.overlay) { + if (settings.overlay && UIOverlay.visible) { const VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); const VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); vkCmdSetViewport(commandBuffer, 0, 1, &viewport); @@ -1217,9 +1217,8 @@ void VulkanExampleBase::handleMessages(HWND hWnd, UINT uMsg, WPARAM wParam, LPAR paused = !paused; break; case KEY_F1: - if (settings.overlay) { - UIOverlay.visible = !UIOverlay.visible; - } + UIOverlay.visible = !UIOverlay.visible; + UIOverlay.updated = true; break; case KEY_ESCAPE: PostQuitMessage(0); @@ -1396,7 +1395,7 @@ int32_t VulkanExampleBase::handleAppInput(struct android_app* app, AInputEvent* bool handled = false; if (vulkanExample->settings.overlay) { ImGuiIO& io = ImGui::GetIO(); - handled = io.WantCaptureMouse; + handled = io.WantCaptureMouse && vulkanExample->UIOverlay.visible; } if (!handled) { int32_t eventX = AMotionEvent_getX(event, 0); @@ -1448,15 +1447,22 @@ int32_t VulkanExampleBase::handleAppInput(struct android_app* app, AInputEvent* case AKEYCODE_BUTTON_Y: vulkanExample->keyPressed(GAMEPAD_BUTTON_Y); break; + case AKEYCODE_1: // support keyboards with no function keys + case AKEYCODE_F1: case AKEYCODE_BUTTON_L1: - vulkanExample->keyPressed(GAMEPAD_BUTTON_L1); + vulkanExample->UIOverlay.visible = !vulkanExample->UIOverlay.visible; + vulkanExample->UIOverlay.updated = true; break; case AKEYCODE_BUTTON_R1: vulkanExample->keyPressed(GAMEPAD_BUTTON_R1); break; + case AKEYCODE_P: case AKEYCODE_BUTTON_START: vulkanExample->paused = !vulkanExample->paused; break; + default: + vulkanExample->keyPressed(keyCode); // handle example-specific key press events + break; }; LOGD("Button %d pressed", keyCode); @@ -1625,23 +1631,28 @@ static CVReturn displayLinkOutputCallback(CVDisplayLinkRef displayLink, const CV { switch (event.keyCode) { - case kVK_ANSI_P: + case KEY_P: vulkanExample->paused = !vulkanExample->paused; break; - case kVK_Delete: // support keyboards with no escape key - case kVK_Escape: + case KEY_1: // support keyboards with no function keys + case KEY_F1: + vulkanExample->UIOverlay.visible = !vulkanExample->UIOverlay.visible; + vulkanExample->UIOverlay.updated = true; + break; + case KEY_DELETE: // support keyboards with no escape key + case KEY_ESCAPE: [NSApp terminate:nil]; break; - case kVK_ANSI_W: + case KEY_W: vulkanExample->camera.keys.up = true; break; - case kVK_ANSI_S: + case KEY_S: vulkanExample->camera.keys.down = true; break; - case kVK_ANSI_A: + case KEY_A: vulkanExample->camera.keys.left = true; break; - case kVK_ANSI_D: + case KEY_D: vulkanExample->camera.keys.right = true; break; default: @@ -1654,16 +1665,16 @@ static CVReturn displayLinkOutputCallback(CVDisplayLinkRef displayLink, const CV { switch (event.keyCode) { - case kVK_ANSI_W: + case KEY_W: vulkanExample->camera.keys.up = false; break; - case kVK_ANSI_S: + case KEY_S: vulkanExample->camera.keys.down = false; break; - case kVK_ANSI_A: + case KEY_A: vulkanExample->camera.keys.left = false; break; - case kVK_ANSI_D: + case KEY_D: vulkanExample->camera.keys.right = false; break; default: @@ -2004,9 +2015,8 @@ void VulkanExampleBase::handleEvent(const DFBWindowEvent *event) paused = !paused; break; case KEY_F1: - if (settings.overlay) { - settings.overlay = !settings.overlay; - } + UIOverlay.visible = !UIOverlay.visible; + UIOverlay.updated = true; break; default: break; @@ -2179,10 +2189,12 @@ void VulkanExampleBase::keyboardKey(struct wl_keyboard *keyboard, paused = !paused; break; case KEY_F1: - if (state && settings.overlay) - settings.overlay = !settings.overlay; + if (state) { + UIOverlay.visible = !UIOverlay.visible; + UIOverlay.updated = true; + } break; - case KEY_ESC: + case KEY_ESCAPE: quit = true; break; } @@ -2540,9 +2552,8 @@ void VulkanExampleBase::handleEvent(const xcb_generic_event_t *event) paused = !paused; break; case KEY_F1: - if (settings.overlay) { - settings.overlay = !settings.overlay; - } + UIOverlay.visible = !UIOverlay.visible; + UIOverlay.updated = true; break; } } @@ -2833,7 +2844,7 @@ void VulkanExampleBase::handleMouseMove(int32_t x, int32_t y) if (settings.overlay) { ImGuiIO& io = ImGui::GetIO(); - handled = io.WantCaptureMouse; + handled = io.WantCaptureMouse && UIOverlay.visible; } mouseMoved((float)x, (float)y, handled); diff --git a/examples/imgui/main.cpp b/examples/imgui/main.cpp index cc802759..91a3b1e0 100644 --- a/examples/imgui/main.cpp +++ b/examples/imgui/main.cpp @@ -596,7 +596,9 @@ public: } // Render imGui - imGui->drawFrame(drawCmdBuffers[i]); + if (UIOverlay.visible) { + imGui->drawFrame(drawCmdBuffers[i]); + } vkCmdEndRenderPass(drawCmdBuffers[i]); @@ -748,8 +750,9 @@ public: io.DeltaTime = frameTimer; io.MousePos = ImVec2(mousePos.x, mousePos.y); - io.MouseDown[0] = mouseButtons.left; - io.MouseDown[1] = mouseButtons.right; + io.MouseDown[0] = mouseButtons.left && UIOverlay.visible; + io.MouseDown[1] = mouseButtons.right && UIOverlay.visible; + io.MouseDown[2] = mouseButtons.middle && UIOverlay.visible; draw(); @@ -765,7 +768,7 @@ public: virtual void mouseMoved(double x, double y, bool &handled) { ImGuiIO& io = ImGui::GetIO(); - handled = io.WantCaptureMouse; + handled = io.WantCaptureMouse && UIOverlay.visible; } }; diff --git a/examples/multithreading/multithreading.cpp b/examples/multithreading/multithreading.cpp index c60d18a9..e071c521 100644 --- a/examples/multithreading/multithreading.cpp +++ b/examples/multithreading/multithreading.cpp @@ -321,9 +321,7 @@ public: vkCmdBindPipeline(secondaryCommandBuffers.ui, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.starsphere); - if (settings.overlay) { - drawUI(secondaryCommandBuffers.ui); - } + drawUI(secondaryCommandBuffers.ui); VK_CHECK_RESULT(vkEndCommandBuffer(secondaryCommandBuffers.ui)); } diff --git a/examples/textoverlay/textoverlay.cpp b/examples/textoverlay/textoverlay.cpp index 2ac70714..ca5cc412 100644 --- a/examples/textoverlay/textoverlay.cpp +++ b/examples/textoverlay/textoverlay.cpp @@ -915,7 +915,6 @@ public: updateTextOverlay(); } -#if !defined(__ANDROID__) virtual void keyPressed(uint32_t keyCode) { switch (keyCode) @@ -925,7 +924,6 @@ public: textOverlay->visible = !textOverlay->visible; } } -#endif }; VULKAN_EXAMPLE_MAIN() diff --git a/xcode/MVKExample.cpp b/xcode/MVKExample.cpp index 82488305..646074ce 100644 --- a/xcode/MVKExample.cpp +++ b/xcode/MVKExample.cpp @@ -23,6 +23,11 @@ void MVKExample::keyPressed(uint32_t keyChar) { // SRS - handle keyboard key case KEY_P: _vulkanExample->paused = !_vulkanExample->paused; break; + case KEY_1: // SRS - support keyboards with no function keys + case KEY_F1: + _vulkanExample->UIOverlay.visible = !_vulkanExample->UIOverlay.visible; + _vulkanExample->UIOverlay.updated = true; + break; default: _vulkanExample->keyPressed(keyChar); break; diff --git a/xcode/macos/DemoViewController.mm b/xcode/macos/DemoViewController.mm index a0a8d308..128931df 100644 --- a/xcode/macos/DemoViewController.mm +++ b/xcode/macos/DemoViewController.mm @@ -97,7 +97,16 @@ MVKExample* _mvkExample; -(void) keyDown:(NSEvent*) theEvent { NSString *text = [theEvent charactersIgnoringModifiers]; unichar keychar = (text.length > 0) ? [text.lowercaseString characterAtIndex: 0] : 0; - _mvkExample->keyDown(keychar); + switch (keychar) + { + case KEY_DELETE: // support keyboards with no escape key + case KEY_ESCAPE: + [NSApp terminate:nil]; + break; + default: + _mvkExample->keyDown(keychar); + break; + } } -(void) keyUp:(NSEvent*) theEvent { From 62f6dcf767f08ae2381a01c958ae100abf0bf1c3 Mon Sep 17 00:00:00 2001 From: Stephen Saunders Date: Mon, 1 Aug 2022 16:52:06 -0400 Subject: [PATCH 31/36] Move macOS benchmarking to NSApp rendering loop, makes example windows visible vs. headless --- base/vulkanexamplebase.cpp | 21 +++++++++++++++++++++ examples/triangle/triangle.cpp | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/base/vulkanexamplebase.cpp b/base/vulkanexamplebase.cpp index d30a94d9..38d20b77 100644 --- a/base/vulkanexamplebase.cpp +++ b/base/vulkanexamplebase.cpp @@ -291,6 +291,9 @@ void VulkanExampleBase::nextFrame() void VulkanExampleBase::renderLoop() { +// SRS - for non-apple plaforms, handle benchmarking here within VulkanExampleBase::renderLoop() +// - for macOS, handle benchmarking within NSApp rendering loop via displayLinkOutputCb() +#if !(defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK)) if (benchmark.active) { benchmark.run([=] { render(); }, vulkanDevice->properties); vkDeviceWaitIdle(device); @@ -299,6 +302,7 @@ void VulkanExampleBase::renderLoop() } return; } +#endif destWidth = width; destHeight = height; @@ -1550,6 +1554,12 @@ dispatch_group_t concurrentGroup; vulkanExample->displayLinkOutputCb(); } }); + + // SRS - When benchmarking, set up termination notification on main thread when concurrent queue completes + if (vulkanExample->benchmark.active) { + dispatch_queue_t notifyQueue = dispatch_get_main_queue(); + dispatch_group_notify(concurrentGroup, notifyQueue, ^{ [NSApp terminate:nil]; }); + } } - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender @@ -1836,6 +1846,17 @@ void* VulkanExampleBase::setupWindow(void* view) void VulkanExampleBase::displayLinkOutputCb() { +#if defined(VK_EXAMPLE_XCODE_GENERATED) + if (benchmark.active) { + benchmark.run([=] { render(); }, vulkanDevice->properties); + if (benchmark.filename != "") { + benchmark.saveResults(); + } + quit = true; // SRS - quit NSApp rendering loop when benchmarking complete + return; + } +#endif + if (prepared) nextFrame(); } diff --git a/examples/triangle/triangle.cpp b/examples/triangle/triangle.cpp index fc775197..dd5ab472 100644 --- a/examples/triangle/triangle.cpp +++ b/examples/triangle/triangle.cpp @@ -1256,7 +1256,7 @@ int main(const int argc, const char *argv[]) vulkanExample->setupWindow(nullptr); vulkanExample->prepare(); vulkanExample->renderLoop(); - delete(vulkanExample); // SRS - handle benchmarking case, normally deleted by applicationWillTerminate() event handler + delete(vulkanExample); } return 0; } From 54d0b27e4a4afab2d2a2b17b466ef16c8453beed Mon Sep 17 00:00:00 2001 From: Stephen Saunders Date: Mon, 1 Aug 2022 19:05:37 -0400 Subject: [PATCH 32/36] Fix ImGui overlay and add extension dependencies for dynamicrendering example --- base/VulkanUIOverlay.cpp | 15 ++++++++++++++- base/VulkanUIOverlay.h | 4 ++-- base/vulkanexamplebase.cpp | 2 +- examples/dynamicrendering/dynamicrendering.cpp | 6 ++++++ 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/base/VulkanUIOverlay.cpp b/base/VulkanUIOverlay.cpp index 96a6307b..df25273f 100644 --- a/base/VulkanUIOverlay.cpp +++ b/base/VulkanUIOverlay.cpp @@ -217,7 +217,7 @@ namespace vks } /** Prepare a separate pipeline for the UI overlay rendering decoupled from the main application */ - void UIOverlay::preparePipeline(const VkPipelineCache pipelineCache, const VkRenderPass renderPass) + void UIOverlay::preparePipeline(const VkPipelineCache pipelineCache, const VkRenderPass renderPass, const VkFormat colorFormat, const VkFormat depthFormat) { // Pipeline layout // Push constants for UI rendering parameters @@ -276,6 +276,19 @@ namespace vks pipelineCreateInfo.stageCount = static_cast(shaders.size()); pipelineCreateInfo.pStages = shaders.data(); pipelineCreateInfo.subpass = subpass; + +#if defined(VK_KHR_dynamic_rendering) + // SRS - if we are using dynamic rendering (i.e. renderPass null), must define color, depth and stencil attachments at pipeline create time + VkPipelineRenderingCreateInfo pipelineRenderingCreateInfo = {}; + if (renderPass == VK_NULL_HANDLE) { + pipelineRenderingCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO; + pipelineRenderingCreateInfo.colorAttachmentCount = 1; + pipelineRenderingCreateInfo.pColorAttachmentFormats = &colorFormat; + pipelineRenderingCreateInfo.depthAttachmentFormat = depthFormat; + pipelineRenderingCreateInfo.stencilAttachmentFormat = depthFormat; + pipelineCreateInfo.pNext = &pipelineRenderingCreateInfo; + } +#endif // Vertex bindings an attributes based on ImGui vertex definition std::vector vertexInputBindings = { diff --git a/base/VulkanUIOverlay.h b/base/VulkanUIOverlay.h index 7d45179b..aa222363 100644 --- a/base/VulkanUIOverlay.h +++ b/base/VulkanUIOverlay.h @@ -69,7 +69,7 @@ namespace vks UIOverlay(); ~UIOverlay(); - void preparePipeline(const VkPipelineCache pipelineCache, const VkRenderPass renderPass); + void preparePipeline(const VkPipelineCache pipelineCache, const VkRenderPass renderPass, const VkFormat colorFormat, const VkFormat depthFormat); void prepareResources(); bool update(); @@ -89,4 +89,4 @@ namespace vks bool button(const char* caption); void text(const char* formatstr, ...); }; -} \ No newline at end of file +} diff --git a/base/vulkanexamplebase.cpp b/base/vulkanexamplebase.cpp index 38d20b77..6d6b7d1b 100644 --- a/base/vulkanexamplebase.cpp +++ b/base/vulkanexamplebase.cpp @@ -217,7 +217,7 @@ void VulkanExampleBase::prepare() loadShader(getShadersPath() + "base/uioverlay.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT), }; UIOverlay.prepareResources(); - UIOverlay.preparePipeline(pipelineCache, renderPass); + UIOverlay.preparePipeline(pipelineCache, renderPass, swapChain.colorFormat, depthFormat); } } diff --git a/examples/dynamicrendering/dynamicrendering.cpp b/examples/dynamicrendering/dynamicrendering.cpp index 5c5712c6..36e3600d 100644 --- a/examples/dynamicrendering/dynamicrendering.cpp +++ b/examples/dynamicrendering/dynamicrendering.cpp @@ -42,6 +42,10 @@ public: camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); enabledInstanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); + enabledDeviceExtensions.push_back(VK_KHR_MAINTENANCE2_EXTENSION_NAME); + enabledDeviceExtensions.push_back(VK_KHR_MULTIVIEW_EXTENSION_NAME); + enabledDeviceExtensions.push_back(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME); + enabledDeviceExtensions.push_back(VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME); enabledDeviceExtensions.push_back(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); } @@ -157,6 +161,8 @@ public: vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); model.draw(drawCmdBuffers[i], vkglTF::RenderFlags::BindImages, pipelineLayout); + + drawUI(drawCmdBuffers[i]); // End dynamic rendering vkCmdEndRenderingKHR(drawCmdBuffers[i]); From 79ec9b126b72b00b9027b070b0f942f67a7dde69 Mon Sep 17 00:00:00 2001 From: Sascha Willems Date: Tue, 2 Aug 2022 10:19:49 +0200 Subject: [PATCH 33/36] Added comment for required extensions --- examples/dynamicrendering/dynamicrendering.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/examples/dynamicrendering/dynamicrendering.cpp b/examples/dynamicrendering/dynamicrendering.cpp index 36e3600d..d7975934 100644 --- a/examples/dynamicrendering/dynamicrendering.cpp +++ b/examples/dynamicrendering/dynamicrendering.cpp @@ -42,11 +42,15 @@ public: camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); enabledInstanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); + + enabledDeviceExtensions.push_back(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); + + // Since we are not requiring Vulkan 1.2, we need to enable some additional extensios as required per the spec enabledDeviceExtensions.push_back(VK_KHR_MAINTENANCE2_EXTENSION_NAME); enabledDeviceExtensions.push_back(VK_KHR_MULTIVIEW_EXTENSION_NAME); enabledDeviceExtensions.push_back(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME); enabledDeviceExtensions.push_back(VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME); - enabledDeviceExtensions.push_back(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); + } ~VulkanExample() From 0f8a349f0cc18ef776bbcc16281e1dc3b7cfa77b Mon Sep 17 00:00:00 2001 From: Sascha Willems Date: Wed, 3 Aug 2022 20:11:40 +0200 Subject: [PATCH 34/36] Get sampler index from UBO instead of passing from VS to FS Fixes #826 --- .../glsl/texturemipmapgen/texture.frag | 19 +++++++++++----- .../glsl/texturemipmapgen/texture.vert | 13 +++-------- .../hlsl/texturemipmapgen/texture.frag | 21 +++++++++++++----- .../hlsl/texturemipmapgen/texture.frag.spv | Bin 3064 -> 2520 bytes .../hlsl/texturemipmapgen/texture.vert | 8 +++---- .../hlsl/texturemipmapgen/texture.vert.spv | Bin 4204 -> 2476 bytes .../texturemipmapgen/texturemipmapgen.cpp | 2 +- 7 files changed, 37 insertions(+), 26 deletions(-) diff --git a/data/shaders/glsl/texturemipmapgen/texture.frag b/data/shaders/glsl/texturemipmapgen/texture.frag index edb92b59..3717d5ec 100644 --- a/data/shaders/glsl/texturemipmapgen/texture.frag +++ b/data/shaders/glsl/texturemipmapgen/texture.frag @@ -5,16 +5,25 @@ layout (set = 0, binding = 2) uniform sampler samplers[3]; layout (location = 0) in vec2 inUV; layout (location = 1) in float inLodBias; -layout (location = 2) flat in int inSamplerIndex; -layout (location = 3) in vec3 inNormal; -layout (location = 4) in vec3 inViewVec; -layout (location = 5) in vec3 inLightVec; +layout (location = 2) in vec3 inNormal; +layout (location = 3) in vec3 inViewVec; +layout (location = 4) in vec3 inLightVec; + +layout (binding = 0) uniform UBO +{ + mat4 projection; + mat4 view; + mat4 model; + vec4 viewPos; + float lodBias; + int samplerIndex; +} ubo; layout (location = 0) out vec4 outFragColor; void main() { - vec4 color = texture(sampler2D(textureColor, samplers[inSamplerIndex]), inUV, inLodBias); + vec4 color = texture(sampler2D(textureColor, samplers[uniform.samplerIndex]), inUV, inLodBias); vec3 N = normalize(inNormal); vec3 L = normalize(inLightVec); diff --git a/data/shaders/glsl/texturemipmapgen/texture.vert b/data/shaders/glsl/texturemipmapgen/texture.vert index 55770880..5d04b795 100644 --- a/data/shaders/glsl/texturemipmapgen/texture.vert +++ b/data/shaders/glsl/texturemipmapgen/texture.vert @@ -16,21 +16,14 @@ layout (binding = 0) uniform UBO layout (location = 0) out vec2 outUV; layout (location = 1) out float outLodBias; -layout (location = 2) flat out int outSamplerIndex; -layout (location = 3) out vec3 outNormal; -layout (location = 4) out vec3 outViewVec; -layout (location = 5) out vec3 outLightVec; - -out gl_PerVertex -{ - vec4 gl_Position; -}; +layout (location = 2) out vec3 outNormal; +layout (location = 3) out vec3 outViewVec; +layout (location = 4) out vec3 outLightVec; void main() { outUV = inUV * vec2(2.0, 1.0); outLodBias = ubo.lodBias; - outSamplerIndex = ubo.samplerIndex; vec3 worldPos = vec3(ubo.model * vec4(inPos, 1.0)); diff --git a/data/shaders/hlsl/texturemipmapgen/texture.frag b/data/shaders/hlsl/texturemipmapgen/texture.frag index 9f58e19d..b14d63d1 100644 --- a/data/shaders/hlsl/texturemipmapgen/texture.frag +++ b/data/shaders/hlsl/texturemipmapgen/texture.frag @@ -3,19 +3,30 @@ Texture2D textureColor : register(t1); SamplerState samplers[3] : register(s2); +struct UBO +{ + float4x4 projection; + float4x4 view; + float4x4 model; + float4 viewPos; + float lodBias; + int samplerIndex; +}; + +cbuffer ubo : register(b0) { UBO ubo; } + struct VSOutput { [[vk::location(0)]] float2 UV : TEXCOORD0; [[vk::location(1)]] float LodBias : TEXCOORD3; -[[vk::location(2)]] int SamplerIndex : TEXCOORD4; -[[vk::location(3)]] float3 Normal : NORMAL0; -[[vk::location(4)]] float3 ViewVec : TEXCOORD1; -[[vk::location(5)]] float3 LightVec : TEXCOORD2; +[[vk::location(2)]] float3 Normal : NORMAL0; +[[vk::location(3)]] float3 ViewVec : TEXCOORD1; +[[vk::location(4)]] float3 LightVec : TEXCOORD2; }; float4 main(VSOutput input) : SV_TARGET { - float4 color = textureColor.Sample(samplers[input.SamplerIndex], input.UV, int2(0, 0), input.LodBias); + float4 color = textureColor.Sample(samplers[ubo.samplerIndex], input.UV, int2(0, 0), input.LodBias); float3 N = normalize(input.Normal); float3 L = normalize(input.LightVec); diff --git a/data/shaders/hlsl/texturemipmapgen/texture.frag.spv b/data/shaders/hlsl/texturemipmapgen/texture.frag.spv index 89a191605803fc93bcf1b4422f94dc211a5a77aa..838dd55024c45d3ba5af262eeb13eb5ada8bec46 100644 GIT binary patch literal 2520 zcmZ9N$x>566o#9`Bn}a9o)8mMoG{Mw0AVnw(IDcmv!c0Lu>zM$g2RrDRjyq5Kt6&C zAI6PU{$HmLUenY`_y3=v&pF+FNvDqHoEvb?4Z6qrW$bV%&oG}B-sZ9%SE^5|rB1g| zx_sq4c7ra>INt?<#O?piyViCb}7(DU2ivG3HES6flwGcGSaP@SG_#%(v-wbwCRR@uQZ zpfbv3Q0r&YHR-Z`jc&CazmMK@o3X0O$_g7g_MsVlL~oq0J#Iv;1V<0BTZlUwcJ!nb zH>R6)xSWqi4?@28R~peLL7&f%=3Z_&W#?RTrSzfRE-lTyoT=3oXZ<;36oZ(3x=W&b zkBA*~k86vM%2j#c!@h4p zaXuS|T9GaFj7k__Y5>z)FnNQC2_|1Keqino7(Xz1ff-=#%$P_2a8cOeb4QYTFnZgM z-Y4~7^o)6B$30*i?M?r2ouTEV3y6S@)L0}^aZ%yh~P=8rg^zDj-db#_&8|>)gRSCMXqSMc768Z#>4ZXcC zfqyO=dVE7deE1itk~6z0fv1kI65bj$=y|K(WKXQJgf~4Uu^7`@vj_WIj2W#h272DN>1KnD zxY+U5pM-p(Ln5QcA-NsPvXMS@8X6Ho++gCd}o3Kb!hqAD^miKE}F(F{0M*(#YRxW)x{ zal?JXec%3_U##+Z?wr=CIaG7{eY;P0pFTY|9qqfjv#c%4vcBvu{&#K8+H=PJM(`C` zSB@vAW~Yj4_4(qV!#C^Kmvy-1w*IU)>qKuy7Av(Sd988UT7OIIaP&j!; zm#NyBN9&R--{}DRN@caOnBSnbWNG$e2EOT?{(IcX^!|O=C#m1uI}w-IykhSlHmBJ7 z#m<)4b7K20_MF&Wi#;c{zhalzxpIbFfk)9JpL5h~7i%~FHqQ65k0AQ*Px#6f?A`Pa zdq28sJN}#4jiG&vD#e=-eUvz}1>HLa-iq#>0$+vhod@vR#y)~*Qy)OGY~z^uwxh`z zYmDxRuSWChIRL_QAWv61zsoy`!Nf-_E?ok;EBO zeH5{_A)@SJ-vNIuySg^x#QVv6r|a0wZC>rW+1n6#@%0JoBi@s6}2FS|9#ZzYT0#Zj33?CLw2GJkhbhjAOR8oM!Wf^#4)Pqg4CTkumY_~{n> zOcS=R&o*K6Z8Txu=Rm@Dliz;&N5k61zK0)n`y=)}{FvJxvG3;}68jU_KOWvE@L_cO zGfh{Vk0XdVjB6~ry+&m(evcZ_LGFCg+_-~C0zH}{OQa~|=G-zI&m z`z1tPALr?1#JP~y$Ju%Xk=Lih{wiXeencPp^BN*w#>csP9WlRWAK<3@*xx|p^_BOV zXU*Qv_ttI>-}_C(99s}`*wYJ$d~f=Oy@l?4O(5EgSl;=*ABGA-Xm9G9BLWBg7b!h`!p5 z<2-ANb04F7F7PMl#=S`YoP|#jedLWT_ZedBy@>WfD2Plz$}Gln(%jF@LS&EGGHlUJTgXMaWa zy!QK2y}zN$yMp^2UC!LW{gF6pndaTB{ZGX6`fDFRyz>UTwz%VM=yKY6*v0=4{dVME D>{sx< diff --git a/data/shaders/hlsl/texturemipmapgen/texture.vert b/data/shaders/hlsl/texturemipmapgen/texture.vert index 8b5f3036..6bcd982d 100644 --- a/data/shaders/hlsl/texturemipmapgen/texture.vert +++ b/data/shaders/hlsl/texturemipmapgen/texture.vert @@ -24,10 +24,9 @@ struct VSOutput float4 Pos : SV_POSITION; [[vk::location(0)]] float2 UV : TEXCOORD0; [[vk::location(1)]] float LodBias : TEXCOORD3; -[[vk::location(2)]] int SamplerIndex : TEXCOORD4; -[[vk::location(3)]] float3 Normal : NORMAL0; -[[vk::location(4)]] float3 ViewVec : TEXCOORD1; -[[vk::location(5)]] float3 LightVec : TEXCOORD2; +[[vk::location(2)]] float3 Normal : NORMAL0; +[[vk::location(3)]] float3 ViewVec : TEXCOORD1; +[[vk::location(4)]] float3 LightVec : TEXCOORD2; }; VSOutput main(VSInput input) @@ -35,7 +34,6 @@ VSOutput main(VSInput input) VSOutput output = (VSOutput)0; output.UV = input.UV * float2(2.0, 1.0); output.LodBias = ubo.lodBias; - output.SamplerIndex = ubo.samplerIndex; float3 worldPos = mul(ubo.model, float4(input.Pos, 1.0)).xyz; diff --git a/data/shaders/hlsl/texturemipmapgen/texture.vert.spv b/data/shaders/hlsl/texturemipmapgen/texture.vert.spv index de4cb54486f9eb5d6da2507997ff422fb91d7abb..cbfc816b9fdae8355ee1ae64995fbc0815b1881a 100644 GIT binary patch literal 2476 zcmZ9N*-}$M5QYarh&v*(xM4!v!3ZvhA`mu16gUyF%G)5hhy@&qO}(Sa^4>?%H}Jv- z@zNWs{J+Vx9x_xr{r|m8cb}PX3+5XPNLYq*4d@nB zE%$+yZ)`_6&OR$yP#*Imuf@>=am6OCIS#*M9K8~ED6w2{&2ezaIC>=Ro5bR-dUaZdb})It^bf`t+!=66d$;g8?O6#u4hGznz{H-H zXce)8yFEOd8q)m9-y^{X-g5Lxrv}4)(piQtNT(*l7o}4Zm@_U(ocs0N@MVvk8`2G< zhbt0%;E_JXac}6KbNlsD_~vjXHXC~G4>QCktB9-GsfW3Ov)Y*nXMuA8(=T{HJN1$i z%(nrX{aV2Eg8h2HqqnEL7Oj&|ZX2me9s_*28UFg@^I z;K13Sw*;KiPORaqbY^9kp16DX5TDo1dp1l@+;PM7#CuL+-g6Q+{x5KDRGI0Mvsm=~ zTa^xJpU_$Kbyq^|VCGnmkjw1%q*L#gaPNkt6c=5_p6~e)3t(s!Nylb>6A3@wviVJV{eKNp!kh(fbrq$vnqVsmB6PtWHwf64U;?$*0g~F6Vp)jlPC%;|I zg{g@tW?1WNeq8E9gVka6sfZpWqycF}NLHAJOh-;ZW*|j=wC^OKfuEV^1AXQ3v61mH zRN_h*r`}uJJBdAO$AI>U7|-jj?e3@!>eH0Pcz)mD(8!+3XxH%W%FVz@f9vY0jSda& z`H!=Xfof&{KxG$xjad%s?ylZ&XAKzJ%vqm|WR0BONMc>g;&hn_c zMn-ElRd$V4YfQ+xJ?zQ#Y(9I~Ti3JooC-ft zTT^y7)#3JigQM-e<-V@|u5!;x%)~a~Stul1|JB!BRW5Jel5BQ4Y3nI(zh-kc7Gs=I zZG0?Cm=DtCo!8qgfz#$&sJC63*&4Gq61F(Z7~f6san`Do&-YYsTbk?a|*mn_cH*g!AYb##9DOc=y z&RXUmTgel4&j}xUlHXLv)yL_VkF$5<4j_?Bu0BpKA6En$cMOR*?Q$n_oW0APOxzN7 zmz>KxlQaK(biZz`$O2CD9>wMr+rL=fdEjRDR>YpPpT@4eh_vvk{l1wa;`G-iq#aLv z<{}rSe5a$EPi(Gv2y0W|`58R0aRv8f-UWz0@{wa9x-|zr1Kkz)Omuq)ya?Sn1wISi z9>msgHc}}3bv&?d%C&+QYcGotedLwM(~9n!UPzv0?9RfvTKFq*{&FEPYiHEL>E4Mx ztwgl3Td$n>9Cl~q+2V5(b{^v8?AC8i@p%b{{rrUOP5T82PuypT`X}PeKbMnNu(y%% zB6jr_rnQn?yE&tdi_v|z+Syh~4wGuLHNS`wfv3dk^YU680X94XnMC z!^_cqXZjfLz4$%?doR`#*n9Dt7ub98o0rFa^YYklo_Gx>c~{or^6vho+IDu&?qI(I z@jS72ac3PqoWuGb$zktwRl@6ucW$c@=OOkE{oiLTVfX)?^XR2(-^gW%G5TrSfVVm2 z)veEO!)AKvWWNj1?l&UNxI6K;;p3V2AaZ^eBJN&va~Wq|v3}ZpWA`E6tKSJZ-`V|$ zyx$Vf@{Juul1k&MbGE;T|b7%TZ?&@u|JN;8@Gl13B>u?r#{}2^ZcQ=wG^Ch~x z;))o*KL^2IA=YAUed7+lM)wY*FW>4nh`citpGcfJBJNvsXXrP>8H)8&Kg_-uiNCw= z(0${9zem^S)|CGwx<2xe{|9vQw<6{g>lb(QBYOUh4uO9{j&5y>5Ni|bXO5Zde<0em9Z5KBYrt}G|7+3ZT>3Y#%W0p( zemSDuI<+?@PWx>1D-i9z1?^3V)834}4$)pjv` setLayoutBindings = { // Binding 0: Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), + vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0), // Binding 1: Sampled image vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT, 1), // Binding 2: Sampler array (3 descriptors) From 465c18862cc9a2719310a31898f9fdb40e3e378e Mon Sep 17 00:00:00 2001 From: Sascha Willems Date: Thu, 4 Aug 2022 17:24:11 +0200 Subject: [PATCH 35/36] Clean up vertex inputs Fixes #766 --- data/shaders/glsl/offscreen/mirror.frag | 3 +-- data/shaders/glsl/offscreen/mirror.frag.spv | Bin 2376 -> 2308 bytes data/shaders/glsl/offscreen/mirror.vert | 5 +---- data/shaders/glsl/offscreen/mirror.vert.spv | Bin 1668 -> 1488 bytes data/shaders/hlsl/offscreen/mirror.frag | 3 +-- data/shaders/hlsl/offscreen/mirror.frag.spv | Bin 2904 -> 1928 bytes data/shaders/hlsl/offscreen/mirror.vert | 5 +---- data/shaders/hlsl/offscreen/mirror.vert.spv | Bin 2184 -> 1224 bytes 8 files changed, 4 insertions(+), 12 deletions(-) diff --git a/data/shaders/glsl/offscreen/mirror.frag b/data/shaders/glsl/offscreen/mirror.frag index 9c784dc2..faa75c59 100644 --- a/data/shaders/glsl/offscreen/mirror.frag +++ b/data/shaders/glsl/offscreen/mirror.frag @@ -2,8 +2,7 @@ layout (binding = 1) uniform sampler2D samplerColor; -layout (location = 0) in vec2 inUV; -layout (location = 1) in vec4 inPos; +layout (location = 0) in vec4 inPos; layout (location = 0) out vec4 outFragColor; diff --git a/data/shaders/glsl/offscreen/mirror.frag.spv b/data/shaders/glsl/offscreen/mirror.frag.spv index 7f382743284bce16aff225531d284ee0af59ec03..a94d88daa7c9201d2ef334733665075db63078ad 100644 GIT binary patch delta 80 zcmX>h)FQ;o%%sfDz`)4B#lXRkGLhF*nuCFbfdPzj6EpLGOa>kxRsdqviHYZV-GNdd X0XZOMnC#2wymIw8c%%%sfDz`)4B0fcE2c}?Xx8CVz?z&JNCGY`mQ-~nOK&NA`(UsY*9!?XwbwH*<(Pg@(b`u zd=(oc?&;|YhOx?B_tvehuIg?!x>IJyY}!uP9jm`NYltyBWl30jTiaV3qiS#C-u=5M zW~>>6Xl9kicU-o=lMnDu$}Y>+WKI1VT7OF1l4?>1Mq7@nemNrER86zDFJ7y15_~~B z7?z*1-6}7&dm| z{?;R&mCr{$cZilfJw7jgQoj^6^l(W&J#a?ySG1yqr#_gOdp_DLGPA>{oadUn6sV7S z;OjEvbic&#&YtU^p66uDiCH|B zlK#)h;9YZGJ{soXng#jrKeP`yi!$=yJ#Se)dCbl8F35-Xyo>V5g-65uc&E(njrL{+ zsm$N5bDhXBFXvVxN6&pti+OcrsSG`F?%=!jC3aOteKb!r9o`%q=ODf=gQFkb=xrIZ PWmf3HXnyO~9?Jdzl3i1S literal 1668 zcmZ9LTTc{05QW zDql=IUvJmCu}N*$Id!VKx_XFe%?amDxk>#!a)UMJYGRz5a?Pmqxv}{T?BWub?iu700{!2;YZcKmw^k8zzezmi!9ZY^!c<3>; z6z`Nh;*pyZ-g*089md`lbjRKDb9zu^rMifvLPL*Vvh*u)I%#(|?N;eGL9qiKpIF(;{GqX%@OsYld{$K3+4mHk#W-8BjXXPk zm-VXs;vgNym@2V;o)2U6=ZCIXJItvrp9N-4V9o?HC&Qb<%z!m6+tjaN?#UYE^dY!e z&kgdZIhqG1@3qYG;Qr6!j-z>C@=j!y2WNTh@Sbqof%jOIu?#l`&|_-Z45-H&v6uzR zIC_I)H;yylq7e=sj&G7)sE2M|zw8ZhXz&;1#o80uk}|jhm{=k_sU0o+^MLub;fV9! zLO&J|_M)Q*;#7QZNeRDUICxI;recd$FJ1}!}2gPVb)9@^_N=T2VH&zighs6`xn zSH^iO!uPb316P;Fd)eHGVf1}pJ3SERT=06}o@!RyiMg@R{T9P_`$8=5b5_RNyi}Ao z1iz7jc`V78A#*~{Y?fv4rnw{^4YM-MW%=+wRfn7v8F}!Q$G1%$Gqt>{^5HEnkxwo> z8fJS<##}$BHuJd=IBi4jX5g5m>23v%d31DhW_epiK6>K3&kxllc1M=T&@damM>zT* Z{y+xDefVA<%9uN|LJvmsM=$zJ_80BwU0DDC diff --git a/data/shaders/hlsl/offscreen/mirror.frag b/data/shaders/hlsl/offscreen/mirror.frag index b9c68b7e..72a3aa73 100644 --- a/data/shaders/hlsl/offscreen/mirror.frag +++ b/data/shaders/hlsl/offscreen/mirror.frag @@ -5,8 +5,7 @@ SamplerState samplerColor : register(s1); struct VSOutput { -[[vk::location(0)]] float2 UV : TEXCOORD0; -[[vk::location(1)]] float4 ProjCoord : POSITION0; +[[vk::location(0)]] float4 ProjCoord : POSITION0; }; float4 main(VSOutput input, bool FrontFacing : SV_IsFrontFace) : SV_TARGET diff --git a/data/shaders/hlsl/offscreen/mirror.frag.spv b/data/shaders/hlsl/offscreen/mirror.frag.spv index 89f23ca2b62227d46b5ee16cf089779a153e130a..ff33a17b7234f326a5960aac350fda1777a5e1d7 100644 GIT binary patch literal 1928 zcmY+E+fGwa5QdjM016h6lYoa-@Ca@c0nq{l5i3fhT7s9RhQ>6Zl$2uh4lhi66Cc25 z^Oz9)ztug>W+gv!+%x}LGbJ7yYj^I9b1vmx>My6)#k{A}wRxG}C~gD?jh$d-_8#$+ ziz9rj+jY2v^q5dBRrc@`#g`O%WD!#nX>sp+FGo_f+vIC}-Y*B!J3*yd`cRgQpWH_I zQ{%8+Uajrc>N35*13&o(rRx4}x#d4Af9Q(jw|gFyz2IZ19uzi<>s#xauRQ;xI>4=V z*zm#P_Pec>H~Fj~fgigXUS^o-iv^BO@N z;@BC1X<&1&XdK((gQ`y7v@oGu^e(}cig*Qd83l#T?+kXUzW|Ak=Lg@=9iJ@sw6sZnU;hX zoJJL6U*MVz`7l=wHawUk2OA#LhYL3SnTgr-XK%={x6eqAz8&+jw`O0GQ{NXXcT6_E zDCSfV?(pSsmp`(`B^TA5yIvRQiOpNw5a9J%-*VTRg5`V*eYfO;3$a4DQ@5q#kD^Oc zp~oG8drk|~B9|Tfs(QpH1ajE5-(oW<$@wQH@VP7CgFE_P$sn|mKSK^v(%Ct3_y=%b zAjWTk-s~K)2LiDl>d&2L1mgT|eyQiIBykQLh|dZ5;eZZ@hoOx$4)lcwIrG9J!8kmY z4hLdcftYbvkWSnlI@ zZP_qiy8B#@Zo<+bUwTpHZ$ezkoFC`0AKsY_KI15QC;|~ h3mJjAQpa`?X>)%O=8Q{{&-Y8(<)kFBV={sU8Dg2w;= literal 2904 zcmZ9N`EQg}6ox-qW(H7Mq)?%XGom7b6Jv~;G)k~Q!!Nd>wfdVGr6FV5nP!|Ccc)Pl z_kG`R-&fp4|17tJ)aUv7o#x6--k$Tm=X~ehbC+p<-}XwDt;n)$ZT1I$9UHQ~Lg~-B z(RJDCY$aBIw$W@E=mTb`m%w_MaSGz~=i03#m9lcS1+9Dc+;shl!}aED1Ey8g_Pu1^0hQu^*bA#`sDtbN5;ku?Yn%bRwZ9! z5gQ+yI5>H5?1tr->u%3?^A9JcZkgPBXmtN1T8XaGUP~w!qfbqY&3EVKyVfp~qvp7A zN?y*n-;Hq!1xC7Zz} z`>?!uqs;BTp8+<2QM#0`&Ha`6er&^cnCm&oU7Os#)41nw0dN?X*FfaE?`d2f@y%3U z1+Ri#e5=12WLa;|Cioh>DzKJux$92(nQ+%QNc=3UHSA|Mw@Gea)=Uv|twU$*iQM%N zwG@%-UNMG)pS{GF=h+BXOA%`xKtHv(xEOp>@om)Fob!Fx$2tb#YALqRfp5Y7?B6#O zL++^3`8i8&p1YMS--G(rLYKQ&=V7g79pmR>t)niFGj|UM$f_3l`B?LU*YMqc^EQ&_ zS=UguWA(RD%e!t}bF6(4)_b5Xzog(*Y>gY{BQw`LW9D3m^_!@1b;0ey_;A6!BSXyZ z{dd2HiMc1*;r4M~!p*<`H2y%s?eoFYcrW38zmRbEa7V)3Pk%dH&$X=2bGa1Qzuf)Z1?+8{ z-aMn-z#R4Kh*(d}{3`Y`;Qko1wtO$&x|WB4`Mz5<`+XRw`*yA286E}d$H) z`p(nC#yqbSF>TEADt-^dJg?!a#XR5Re+wMWWBhfX?mYU|@~yuC$^{?7z6mNI?%iAX zo{7J|e&aoR8>q*6-odx;b`d|0uNL|5;(K16tKYu|jstb?hT8kUy2fJe5AdDacM!Ec z#8;2GKf>>UnEPXVwaEVjKb`wixH;-E_hZ;9Ata2Hq#z%~99&LR8JH9#QE@0&mtK+K~D`DlQ_z!Xo_z!n50>c0R diff --git a/data/shaders/hlsl/offscreen/mirror.vert b/data/shaders/hlsl/offscreen/mirror.vert index 671a3138..f7c547eb 100644 --- a/data/shaders/hlsl/offscreen/mirror.vert +++ b/data/shaders/hlsl/offscreen/mirror.vert @@ -3,7 +3,6 @@ struct VSInput { [[vk::location(0)]] float3 Pos : POSITION0; -[[vk::location(1)]] float2 UV : TEXCOORD0; }; struct UBO @@ -18,14 +17,12 @@ cbuffer ubo : register(b0) { UBO ubo; } struct VSOutput { float4 Pos : SV_POSITION; -[[vk::location(0)]] float2 UV : TEXCOORD0; -[[vk::location(1)]] float4 ProjCoord : POSITION0; +[[vk::location(0)]] float4 ProjCoord : POSITION0; }; VSOutput main(VSInput input) { VSOutput output = (VSOutput)0; - output.UV = input.UV; output.ProjCoord = mul(ubo.projection, mul(ubo.view, mul(ubo.model, float4(input.Pos.xyz, 1.0)))); output.Pos = output.ProjCoord; return output; diff --git a/data/shaders/hlsl/offscreen/mirror.vert.spv b/data/shaders/hlsl/offscreen/mirror.vert.spv index 6c1d5e98c607fceb0651fbc19c82d59be0ec62b2..83e55df278e131aa281f5e37beb66563fb6209d4 100644 GIT binary patch literal 1224 zcmZvaO;1x%5QdMfZAAs-8x`vG#D`H~&+yEPk5q|(+7d65qq(I#96ZpAoOnjcp z8PgQc&D@!J=j%OlZ@t!SrF18yG?O-Xd*)ItBlXHRI-BnOvyb+N$2v8{jJuVtrv~}} zuu(lJjeegDdS?eEaB7le+#}SWvWflub06(c47ahlbdxPC$Pyn^TzAsY~3Xiy~HN# z#G)>~Q}Enk6Jq8pWBVr*$O;uxXnkv!c;81Ch&*0pKXw@Y!-@DbzP*jxYX(W_^1~|r zES59u-_AP}3u$L=?yMlo9okF2@|#23vyK>_N6SrIe*taG84FY{qB|f)gg_lZBj*^d$Dxktr3xjaFP zMcz~F$aBY$w}x#j@}7<5x%t#H#CJ0wuMr}okFXYSZ-5WjNkYP{#?J9 z_&%p+nw#n+!_526a%Se9+the|(z!9`+>|@ef1VjP9+;HJc&FW|q1~>x4gup5A|@nh zNyg)pxA){s>+giP?P|H->-2jv6*J*E>`MH7h&iLSjX&f4)UI^ngVi|hHe^$4R=W4I z(=7D&VwpY{jt45OZZ62KJumw@*gPH8Y3}!0vAWJE3ZCQ4GuTZe_Cdbdz1SJ$`J%cZ+=D{j*7Ao#Xk?yQ!}n=ghw_7eAdJ~8PekA0ahSv0L3 z(Vy)Zyd=C`T|Z=v>=4XjI|SPf(~5|MJN0h8?N4s`yrS}WSEnUBU}nyGG{C%1Ftza0 zf6`CSNk2PUmhcb{&UxhATG%x({~wOnbCNaX*}I}Y%cBSKo{n&%dBi32n2Ee&iPeG| z&4aT%yGPb%QEwHFn0eXU{z$T*jFZw}a>48qOl(#&bLWYHM;DY2cSbU&__NZHguZVF zJT-!+g?Y@+o~RGztQm=O$4?f8=VWmX{ct|Jgfq#8S>Pi@otLH-^U?o;G&NHa{PWWE z1`l2gn0de#rHSQC@TGw9&#Lle>6{|2NMmOe!~LY5)!+{CKHzim-;!oW@YK8`jUNtN z2-x!P2{VJubU$EbCVoYle4C*dFg-t#pB><*2AG+##{y<%W;D#q>=%xBX6D;4jDPU^ z=iCE%n44T4_V8QPuS%24Y_BAoZ@84egB=X~D~e}^oP_?s>|j~K*%h6|4)YRX;2+Bq zNyA}t7I*KNV%cLw5=ppoR&PT#yv1zFCXX0ufQiA+?yC~|=bpl`|1AkT9CdjYH3_`s z=_mf5yw~F3tsnAsB=DB^M)v4=Z^gm$ZPf+mz;HM|!_5;s+#x-Qavn%>8N;f6!pV``K}4Wu_J0 Date: Sat, 6 Aug 2022 10:16:54 +0200 Subject: [PATCH 36/36] Slightly reworked glTF samples Parent matrices are now applied (where available) Now more in line with the base code glTF loader Refs #964 --- data/shaders/glsl/gltfloading/mesh.frag | 2 +- data/shaders/glsl/gltfloading/mesh.frag.spv | Bin 2024 -> 2008 bytes data/shaders/glsl/gltfloading/mesh.vert | 5 +- data/shaders/glsl/gltfloading/mesh.vert.spv | Bin 3212 -> 3396 bytes data/shaders/hlsl/gltfloading/mesh.frag | 2 +- data/shaders/hlsl/gltfloading/mesh.frag.spv | Bin 1776 -> 1752 bytes data/shaders/hlsl/gltfloading/mesh.vert | 6 +-- data/shaders/hlsl/gltfloading/mesh.vert.spv | Bin 2400 -> 2516 bytes examples/gltfloading/gltfloading.cpp | 47 +++++++++++------- .../gltfscenerendering/gltfscenerendering.cpp | 46 +++++++++-------- .../gltfscenerendering/gltfscenerendering.h | 13 +++-- 11 files changed, 71 insertions(+), 50 deletions(-) diff --git a/data/shaders/glsl/gltfloading/mesh.frag b/data/shaders/glsl/gltfloading/mesh.frag index fb415cef..866dd316 100644 --- a/data/shaders/glsl/gltfloading/mesh.frag +++ b/data/shaders/glsl/gltfloading/mesh.frag @@ -17,7 +17,7 @@ void main() vec3 N = normalize(inNormal); vec3 L = normalize(inLightVec); vec3 V = normalize(inViewVec); - vec3 R = reflect(-L, N); + vec3 R = reflect(L, N); vec3 diffuse = max(dot(N, L), 0.15) * inColor; vec3 specular = pow(max(dot(R, V), 0.0), 16.0) * vec3(0.75); outFragColor = vec4(diffuse * color.rgb + specular, 1.0); diff --git a/data/shaders/glsl/gltfloading/mesh.frag.spv b/data/shaders/glsl/gltfloading/mesh.frag.spv index 5cd562653a43a2f4e3575be29980fd2deef432dd..00c5c46a45b9941d4a8407d03e5a1486b1dd4378 100644 GIT binary patch delta 787 zcmXw%$x1^(6hv>EIHHIkqApYrQ83O!95Wc_SzNjjjUWh4WF1|IJ3(}#zmd=I2i&{y z7hDLQdcNDCNZsn{+tuCgyZN)ZDN)s1YZk1*>TLJ9=_nMQ&%gRc%f5X0N$KMF28vQ+g_rB_7z&l2a2U!Hi0^M5nL$f3Wi~Gt!|TPUy32c=jp|%Bg}W7= z1JWEl^jV@#0P@lAzb?euG!d%cNx*pdNEBNX+Pz)ybS0m>4CO^k+F}TFgGNlMhd}^q zAO$p^VZ%ZGHRtO_;acbQ7`zv}Mz>%#4wpx|dh7U;K)nad%8^0$;|-?ZZQzLp3Nj6( zX^{fx9MarB16L@oXW{+81I)qYk?sK&;Qs;2W-{nOd@>VHcJeQy9>>Gv;W;3W!sz9t z`R2=T1yrreUIF!BkMBo^S&cR68iD=QAilsiBTv_OV-pwsDd(%dgCX22h>xH;$m delta 803 zcmXw%%Pxaa6ot=eOG$`GL@+=iLZa?e-KwSTml8uGp%RJ2rRn%*AZ8M&39sQXynwlh zS1^$H)}OP_pOt^@wfEU)oy%9-Pg`p;F_3o7yC%N!OY4a*yo|iqbt>K{gW?!{Q6@b%^<$Nb>~N1ij;Fps$y82kE8pd#f3O7tYoO} zfER%@LqC1ih?4++ZZX8Apk=X;fTsYX{+X<_%e2+@!gC+R)U}TyinPQi$bjV#kHPyu z3zL)|2Oew!)heIIzzBckY~CbX^DLf%4}jPBRGgcJt42D#qxd{#3DkTTs6gjs4YKe~ z@Js_4nFG=^M+USnX;wcEmnn-E;6uO+EW%YIy~Rc8*uXM@8Bl>PNITbMt%O_;f7R)- z%*-lWm!le)(MynKi?73FP_Yhw12ls&?@624jDo0yhD_+@9>Z?8;A)~{x2D^0E%Xp- wcHpX$eiV**7cO1Hv^}^qtzp{Ieh{_jAs*%O0H}c`DBlINJ3TMu{%DZ{{}!7&HUIzs diff --git a/data/shaders/glsl/gltfloading/mesh.vert b/data/shaders/glsl/gltfloading/mesh.vert index 2760684e..e2da4ece 100644 --- a/data/shaders/glsl/gltfloading/mesh.vert +++ b/data/shaders/glsl/gltfloading/mesh.vert @@ -10,6 +10,7 @@ layout (set = 0, binding = 0) uniform UBOScene mat4 projection; mat4 view; vec4 lightPos; + vec4 viewPos; } uboScene; layout(push_constant) uniform PushConsts { @@ -32,6 +33,6 @@ void main() vec4 pos = uboScene.view * vec4(inPos, 1.0); outNormal = mat3(uboScene.view) * inNormal; vec3 lPos = mat3(uboScene.view) * uboScene.lightPos.xyz; - outLightVec = lPos - pos.xyz; - outViewVec = -pos.xyz; + outLightVec = uboScene.lightPos.xyz - pos.xyz; + outViewVec = uboScene.viewPos.xyz - pos.xyz; } \ No newline at end of file diff --git a/data/shaders/glsl/gltfloading/mesh.vert.spv b/data/shaders/glsl/gltfloading/mesh.vert.spv index cf6fc4ac34758c1159e7f64a2d1acf8dcb20d627..4fe54ca90a060b0128efceed21f91f47db70256f 100644 GIT binary patch delta 407 zcmYk2u}T9`5JhKpHycrc1R)SbG;Zk+Sg2r^E`ES%jH_;9j1o|+L~JdTCHNh(g+E~H zmsnd0o-01cz~Q~QbKlJHp4uO)jX28cW^RkNVAn5=kr!`wQ(sA~W}9Xf!%dOj9!{p^ zm(RSY9-^K%yL06X%X9e|zf#PTnJ=e*FE@}ytE#1I-YmGP*|sIN&N-|)_4lN6K%+kC z0Jh)=_OP@#Phe1fFJ<>ZIYrrp9?P<|oq;r=aERcMuBx9y4)X0Y{`g-DQ%B^QI)pIe sg1huEV{A4yi9!*Ega?;s^Gi+0r3ppwho!F2Xln9lDgBJJADlbz3r}z?1ONa4 delta 219 zcmX>i)g#Hv%%sfDz`)4B0fgBTd9xYQH&zxiPGXwEn7(-`lRx9+AIuacAsL8+fEdIV1JWr#Y%|%EM|rXgFGo%qkOxwc z3dD8{%nV6D8YBi&odIOq0I@&NB_Pu>ffytP!XUs1#7sb3549}|$OfqanUxNtLHxf! IRTe-D0G+cPF#rGn diff --git a/data/shaders/hlsl/gltfloading/mesh.frag b/data/shaders/hlsl/gltfloading/mesh.frag index 914421a0..a574c7a1 100644 --- a/data/shaders/hlsl/gltfloading/mesh.frag +++ b/data/shaders/hlsl/gltfloading/mesh.frag @@ -24,7 +24,7 @@ float4 main(VSOutput input) : SV_TARGET float3 N = normalize(input.Normal); float3 L = normalize(input.LightVec); float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); + float3 R = reflect(L, N); float3 diffuse = max(dot(N, L), 0.0) * input.Color; float3 specular = pow(max(dot(R, V), 0.0), 16.0) * float3(0.75, 0.75, 0.75); return float4(diffuse * color.rgb + specular, 1.0); diff --git a/data/shaders/hlsl/gltfloading/mesh.frag.spv b/data/shaders/hlsl/gltfloading/mesh.frag.spv index a801c5f2114e0f397e424ddabce3fe5173ec1f66..4eafff863c6604e2e264c40899236d08812e6d97 100644 GIT binary patch delta 375 zcmXw!O=s}LlUXrx1-h_D z;psU%gEeVtL2lP6c#EBukUZSCN9wI&Z$PxJ56S;SD%GQ4(YIRF(wux8Ayme7VmtQN zvF4+Ep!FE(H$H1aZjHZG+mffbRQs%IY_|CiFL@&Fzy=<$-~kFXSbgvPb50I7_$L*K delta 399 zcmXw!O-=$q6od2{n(oO| zUUj{C)vpivG0z+IUQ?<`y3+bD|IErt7rN#A2!^1gW;j2=?b`tN?!m7z=A`GJ@2sds zFgyBIzzz7q;j|af1@@$=67JLo;9HzD1}VdRXQbXF_BvGi+92gmrAh^YP4Bu4m%hRW z5tI;Ir|#oYZ*VVW-!5u1xOD=xjnA9It@}&b0&dOAp0%aKA4FgB!He#wE8qYRxPKjL MgB8!ce@>G4U&CBWs{bV8Qr}#6Q5#^^1w` zvpc6*I?Z9ud+z7V%#v##>vXQoIoIRX^q1A=+Px%~V6>O?W5Mrjg$?+25f&Yyyr>{j zFn3OLUeqP(7UlFqzb%Kneiy{YzxV6qqwPqn{5ldDJfghpFN*&%A4pe7cy#**(a-v~ zIE<9NAS-OB=QynYLT|RzwHyA}iEGheDo<^x6sR4Q2)l-W72 zTMstYDy!1uH96+!<(rFNt3j}_(DY$`URMoPgAEkKV&2hFoFuYf$T z-tjvTSuFZTcIsuk8x}Iwk|u-7m@`iTeGbeQPjy<}Y+POQ(z;>tT6MRd1n}|NaMeWp19&pKHvmf;s`+jBR z97^)ItsNepJKCwoYPc(&8o=~;Pdo9*gZ+K&*pqWwn0~mw$iVc#eIy3h-a%Ui6U#6? zF+aoD^WF>>#q)mgAzn#4cPEQ^e}?Iq+=j8|{bh0bKft+3Wg3%?TrB4DSDif2KBHXp z{ZK@2hR4Md3(Q;}iKyT7kHu4eMO8D~vWWR`k09)r?Gq6?v*Y_|cHB|3<9mm$qNtqB zgoycOV?FosPqN{Tz7SD2%VaObBcoT7O?nyq)ihPk^pyyI?9p@IPZby4ln6cfO!nH# zsncX{#3QFilTC}q7d!G3@2$t$T%i9D%zH+J9AZ%~^_kB*@x(xGKC|MHL#$SxImz%L zj`>u?&w0|;^r`9GxbyQOY9ThZ^g(@95qAJRXUBV35ZT%B{ow5AZ_(>4=X)@^i<8v=dMhxsM_lkJS&9}^Qe-Mw(Vt*8m3}Us$UX=_RV!zW3=go1B@SWP} c8=kku9f#+gasT1Fv=alqTRXM>Qwe|XND&;S4c literal 2400 zcmZ9MYfn=_5QY~@i=ZNiT)bfm-qEV4h$2EM2pHs4#KfvXQoIoIRf>7Ui-+JhwLG1?3IvEX+%;|6@Y2#XF;UQ`e% zm^<5_OBtigNm)-;zUKzjNZ#pL_N4;Z`D6ejQ#0k0>wu^Ws0vN75BMk8W>2`Ck8$ z#)+~QWQ7g&9L4n?=*^b8cH(c_X)QTGPP`uN&Dh<(6Q93!c(7ef8VBiSBQ2i*??e1% z$LcrvTHo<;@~&6=-hR9rr}0tU%R2oW;zs#sbH7}RKCW!6L~DshBd+<;6Ml0ovQ|IrvVQcA-?4~T zya$%mu%u}q!w$XOL(^wv*<5DV>^R3oPYq!D zyRDsgVx zE5jx6*Y!IxgbuP5(eV z^;c9ivwbLHKHMP)J7!xJp)`<5w#F| zPDCHnH!tE2py%v(4^@$!9p4Vlj{X*c&T=jW8FH58wAgPY!-m-Avm~C`K`it69qL(@ w3_t9CDK9my1pG!fmAAur!1HdXAD%bEU4`$`&OL_bt>6#OJ0bo*Wt|fJ2aOk$zyJUM diff --git a/examples/gltfloading/gltfloading.cpp b/examples/gltfloading/gltfloading.cpp index 1aa42647..7a38fcef 100644 --- a/examples/gltfloading/gltfloading.cpp +++ b/examples/gltfloading/gltfloading.cpp @@ -1,7 +1,7 @@ /* * Vulkan Example - glTF scene loading and rendering * -* Copyright (C) 2020-2021 by Sascha Willems - www.saschawillems.de +* Copyright (C) 2020-2022 by Sascha Willems - www.saschawillems.de * * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) */ @@ -78,9 +78,14 @@ public: // A node represents an object in the glTF scene graph struct Node { Node* parent; - std::vector children; + std::vector children; Mesh mesh; glm::mat4 matrix; + ~Node() { + for (auto& child : children) { + delete child; + } + } }; // A glTF material stores information in e.g. the texture that is attached to it and colors @@ -109,10 +114,13 @@ public: std::vector images; std::vector textures; std::vector materials; - std::vector nodes; + std::vector nodes; ~VulkanglTFModel() { + for (auto node : nodes) { + delete node; + } // Release all Vulkan resources allocated for the model vkDestroyBuffer(vulkanDevice->logicalDevice, vertices.buffer, nullptr); vkFreeMemory(vulkanDevice->logicalDevice, vertices.memory, nullptr); @@ -195,29 +203,30 @@ public: void loadNode(const tinygltf::Node& inputNode, const tinygltf::Model& input, VulkanglTFModel::Node* parent, std::vector& indexBuffer, std::vector& vertexBuffer) { - VulkanglTFModel::Node node{}; - node.matrix = glm::mat4(1.0f); + VulkanglTFModel::Node* node = new VulkanglTFModel::Node{}; + node->matrix = glm::mat4(1.0f); + node->parent = parent; // Get the local node matrix // It's either made up from translation, rotation, scale or a 4x4 matrix if (inputNode.translation.size() == 3) { - node.matrix = glm::translate(node.matrix, glm::vec3(glm::make_vec3(inputNode.translation.data()))); + node->matrix = glm::translate(node->matrix, glm::vec3(glm::make_vec3(inputNode.translation.data()))); } if (inputNode.rotation.size() == 4) { glm::quat q = glm::make_quat(inputNode.rotation.data()); - node.matrix *= glm::mat4(q); + node->matrix *= glm::mat4(q); } if (inputNode.scale.size() == 3) { - node.matrix = glm::scale(node.matrix, glm::vec3(glm::make_vec3(inputNode.scale.data()))); + node->matrix = glm::scale(node->matrix, glm::vec3(glm::make_vec3(inputNode.scale.data()))); } if (inputNode.matrix.size() == 16) { - node.matrix = glm::make_mat4x4(inputNode.matrix.data()); + node->matrix = glm::make_mat4x4(inputNode.matrix.data()); }; // Load node's children if (inputNode.children.size() > 0) { for (size_t i = 0; i < inputNode.children.size(); i++) { - loadNode(input.nodes[inputNode.children[i]], input , &node, indexBuffer, vertexBuffer); + loadNode(input.nodes[inputNode.children[i]], input , node, indexBuffer, vertexBuffer); } } @@ -309,7 +318,7 @@ public: primitive.firstIndex = firstIndex; primitive.indexCount = indexCount; primitive.materialIndex = glTFPrimitive.material; - node.mesh.primitives.push_back(primitive); + node->mesh.primitives.push_back(primitive); } } @@ -326,20 +335,20 @@ public: */ // Draw a single node including child nodes (if present) - void drawNode(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout, VulkanglTFModel::Node node) + void drawNode(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout, VulkanglTFModel::Node* node) { - if (node.mesh.primitives.size() > 0) { + if (node->mesh.primitives.size() > 0) { // Pass the node's matrix via push constants // Traverse the node hierarchy to the top-most parent to get the final matrix of the current node - glm::mat4 nodeMatrix = node.matrix; - VulkanglTFModel::Node* currentParent = node.parent; + glm::mat4 nodeMatrix = node->matrix; + VulkanglTFModel::Node* currentParent = node->parent; while (currentParent) { nodeMatrix = currentParent->matrix * nodeMatrix; currentParent = currentParent->parent; } // Pass the final matrix to the vertex shader using push constants vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::mat4), &nodeMatrix); - for (VulkanglTFModel::Primitive& primitive : node.mesh.primitives) { + for (VulkanglTFModel::Primitive& primitive : node->mesh.primitives) { if (primitive.indexCount > 0) { // Get the texture index for this primitive VulkanglTFModel::Texture texture = textures[materials[primitive.materialIndex].baseColorTextureIndex]; @@ -349,7 +358,7 @@ public: } } } - for (auto& child : node.children) { + for (auto& child : node->children) { drawNode(commandBuffer, pipelineLayout, child); } } @@ -382,6 +391,7 @@ public: glm::mat4 projection; glm::mat4 model; glm::vec4 lightPos = glm::vec4(5.0f, 5.0f, -5.0f, 1.0f); + glm::vec4 viewPos; } values; } shaderData; @@ -404,7 +414,7 @@ public: camera.type = Camera::CameraType::lookat; camera.flipY = true; camera.setPosition(glm::vec3(0.0f, -0.1f, -1.0f)); - camera.setRotation(glm::vec3(0.0f, -135.0f, 0.0f)); + camera.setRotation(glm::vec3(0.0f, 45.0f, 0.0f)); camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); } @@ -707,6 +717,7 @@ public: { shaderData.values.projection = camera.matrices.perspective; shaderData.values.model = camera.matrices.view; + shaderData.values.viewPos = camera.viewPos; memcpy(shaderData.buffer.mapped, &shaderData.values, sizeof(shaderData.values)); } diff --git a/examples/gltfscenerendering/gltfscenerendering.cpp b/examples/gltfscenerendering/gltfscenerendering.cpp index 9090317a..7ba5ee0f 100644 --- a/examples/gltfscenerendering/gltfscenerendering.cpp +++ b/examples/gltfscenerendering/gltfscenerendering.cpp @@ -1,7 +1,7 @@ /* * Vulkan Example - Scene rendering * -* Copyright (C) 2020-2021 by Sascha Willems - www.saschawillems.de +* Copyright (C) 2020-202- by Sascha Willems - www.saschawillems.de * * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) * @@ -20,6 +20,9 @@ VulkanglTFScene::~VulkanglTFScene() { + for (auto node : nodes) { + delete node; + } // Release all Vulkan resources allocated for the model vkDestroyBuffer(vulkanDevice->logicalDevice, vertices.buffer, nullptr); vkFreeMemory(vulkanDevice->logicalDevice, vertices.memory, nullptr); @@ -87,30 +90,31 @@ void VulkanglTFScene::loadMaterials(tinygltf::Model& input) void VulkanglTFScene::loadNode(const tinygltf::Node& inputNode, const tinygltf::Model& input, VulkanglTFScene::Node* parent, std::vector& indexBuffer, std::vector& vertexBuffer) { - VulkanglTFScene::Node node{}; - node.name = inputNode.name; + VulkanglTFScene::Node* node = new VulkanglTFScene::Node{}; + node->name = inputNode.name; + node->parent = parent; // Get the local node matrix // It's either made up from translation, rotation, scale or a 4x4 matrix - node.matrix = glm::mat4(1.0f); + node->matrix = glm::mat4(1.0f); if (inputNode.translation.size() == 3) { - node.matrix = glm::translate(node.matrix, glm::vec3(glm::make_vec3(inputNode.translation.data()))); + node->matrix = glm::translate(node->matrix, glm::vec3(glm::make_vec3(inputNode.translation.data()))); } if (inputNode.rotation.size() == 4) { glm::quat q = glm::make_quat(inputNode.rotation.data()); - node.matrix *= glm::mat4(q); + node->matrix *= glm::mat4(q); } if (inputNode.scale.size() == 3) { - node.matrix = glm::scale(node.matrix, glm::vec3(glm::make_vec3(inputNode.scale.data()))); + node->matrix = glm::scale(node->matrix, glm::vec3(glm::make_vec3(inputNode.scale.data()))); } if (inputNode.matrix.size() == 16) { - node.matrix = glm::make_mat4x4(inputNode.matrix.data()); + node->matrix = glm::make_mat4x4(inputNode.matrix.data()); }; // Load node's children if (inputNode.children.size() > 0) { for (size_t i = 0; i < inputNode.children.size(); i++) { - loadNode(input.nodes[inputNode.children[i]], input, &node, indexBuffer, vertexBuffer); + loadNode(input.nodes[inputNode.children[i]], input, node, indexBuffer, vertexBuffer); } } @@ -210,7 +214,7 @@ void VulkanglTFScene::loadNode(const tinygltf::Node& inputNode, const tinygltf:: primitive.firstIndex = firstIndex; primitive.indexCount = indexCount; primitive.materialIndex = glTFPrimitive.material; - node.mesh.primitives.push_back(primitive); + node->mesh.primitives.push_back(primitive); } } @@ -232,23 +236,23 @@ VkDescriptorImageInfo VulkanglTFScene::getTextureDescriptor(const size_t index) */ // Draw a single node including child nodes (if present) -void VulkanglTFScene::drawNode(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout, VulkanglTFScene::Node node) +void VulkanglTFScene::drawNode(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout, VulkanglTFScene::Node* node) { - if (!node.visible) { + if (!node->visible) { return; } - if (node.mesh.primitives.size() > 0) { + if (node->mesh.primitives.size() > 0) { // Pass the node's matrix via push constants // Traverse the node hierarchy to the top-most parent to get the final matrix of the current node - glm::mat4 nodeMatrix = node.matrix; - VulkanglTFScene::Node* currentParent = node.parent; + glm::mat4 nodeMatrix = node->matrix; + VulkanglTFScene::Node* currentParent = node->parent; while (currentParent) { nodeMatrix = currentParent->matrix * nodeMatrix; currentParent = currentParent->parent; } // Pass the final matrix to the vertex shader using push constants vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::mat4), &nodeMatrix); - for (VulkanglTFScene::Primitive& primitive : node.mesh.primitives) { + for (VulkanglTFScene::Primitive& primitive : node->mesh.primitives) { if (primitive.indexCount > 0) { VulkanglTFScene::Material& material = materials[primitive.materialIndex]; // POI: Bind the pipeline for the node's material @@ -258,7 +262,7 @@ void VulkanglTFScene::drawNode(VkCommandBuffer commandBuffer, VkPipelineLayout p } } } - for (auto& child : node.children) { + for (auto& child : node->children) { drawNode(commandBuffer, pipelineLayout, child); } } @@ -641,21 +645,21 @@ void VulkanExample::OnUpdateUIOverlay(vks::UIOverlay* overlay) if (overlay->header("Visibility")) { if (overlay->button("All")) { - std::for_each(glTFScene.nodes.begin(), glTFScene.nodes.end(), [](VulkanglTFScene::Node &node) { node.visible = true; }); + std::for_each(glTFScene.nodes.begin(), glTFScene.nodes.end(), [](VulkanglTFScene::Node* node) { node->visible = true; }); buildCommandBuffers(); } ImGui::SameLine(); if (overlay->button("None")) { - std::for_each(glTFScene.nodes.begin(), glTFScene.nodes.end(), [](VulkanglTFScene::Node &node) { node.visible = false; }); + std::for_each(glTFScene.nodes.begin(), glTFScene.nodes.end(), [](VulkanglTFScene::Node* node) { node->visible = false; }); buildCommandBuffers(); } ImGui::NewLine(); // POI: Create a list of glTF nodes for visibility toggle ImGui::BeginChild("#nodelist", ImVec2(200.0f * overlay->scale, 340.0f * overlay->scale), false); - for (auto &node : glTFScene.nodes) + for (auto& node : glTFScene.nodes) { - if (overlay->checkBox(node.name.c_str(), &node.visible)) + if (overlay->checkBox(node->name.c_str(), &node->visible)) { buildCommandBuffers(); } diff --git a/examples/gltfscenerendering/gltfscenerendering.h b/examples/gltfscenerendering/gltfscenerendering.h index 1e1d673c..b29c90b1 100644 --- a/examples/gltfscenerendering/gltfscenerendering.h +++ b/examples/gltfscenerendering/gltfscenerendering.h @@ -1,7 +1,7 @@ /* * Vulkan Example - Scene rendering * -* Copyright (C) 2020 by Sascha Willems - www.saschawillems.de +* Copyright (C) 2020-2022 by Sascha Willems - www.saschawillems.de * * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) * @@ -76,11 +76,16 @@ public: // A node represents an object in the glTF scene graph struct Node { Node* parent; - std::vector children; + std::vector children; Mesh mesh; glm::mat4 matrix; std::string name; bool visible = true; + ~Node() { + for (auto& child : children) { + delete child; + } + } }; // A glTF material stores information in e.g. the texture that is attached to it and colors @@ -113,7 +118,7 @@ public: std::vector images; std::vector textures; std::vector materials; - std::vector nodes; + std::vector nodes; std::string path; @@ -123,7 +128,7 @@ public: void loadTextures(tinygltf::Model& input); void loadMaterials(tinygltf::Model& input); void loadNode(const tinygltf::Node& inputNode, const tinygltf::Model& input, VulkanglTFScene::Node* parent, std::vector& indexBuffer, std::vector& vertexBuffer); - void drawNode(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout, VulkanglTFScene::Node node); + void drawNode(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout, VulkanglTFScene::Node* node); void draw(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout); };