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/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..6d6b7d1b 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 @@ -218,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); } } @@ -292,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); @@ -300,6 +302,7 @@ void VulkanExampleBase::renderLoop() } return; } +#endif destWidth = width; destHeight = height; @@ -667,8 +670,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 +712,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 +1221,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 +1399,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 +1451,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); @@ -1544,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 @@ -1625,23 +1641,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 +1675,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: @@ -1825,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(); } @@ -2004,9 +2036,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 +2210,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 +2573,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 +2865,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/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]); 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/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; } 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 {