diff --git a/base/vulkanexamplebase.cpp b/base/vulkanexamplebase.cpp index d0492d64..a84b612b 100644 --- a/base/vulkanexamplebase.cpp +++ b/base/vulkanexamplebase.cpp @@ -59,7 +59,7 @@ VkResult VulkanExampleBase::createDevice(VkDeviceQueueCreateInfo requestedQueues deviceCreateInfo.pNext = NULL; deviceCreateInfo.queueCreateInfoCount = 1; deviceCreateInfo.pQueueCreateInfos = &requestedQueues; - deviceCreateInfo.pEnabledFeatures = nullptr; + deviceCreateInfo.pEnabledFeatures = &enabledFeatures; // enable the debug marker extension if it is present (likely meaning a debugging tool is present) if (vkTools::checkDeviceExtensionPresent(physicalDevice, VK_EXT_DEBUG_MARKER_EXTENSION_NAME)) @@ -641,35 +641,6 @@ void VulkanExampleBase::prepareFrame() { // Acquire the next image from the swap chaing VK_CHECK_RESULT(swapChain.acquireNextImage(semaphores.presentComplete, ¤tBuffer)); -/* - // Insert a post present image barrier to transform the image back to a - // color attachment that our render pass can write to - // We always use undefined image layout as the source as it doesn't actually matter - // what is done with the previous image contents - VkCommandBufferBeginInfo cmdBufInfo = vkTools::initializers::commandBufferBeginInfo(); - VK_CHECK_RESULT(vkBeginCommandBuffer(postPresentCmdBuffer, &cmdBufInfo)); - - VkImageMemoryBarrier postPresentBarrier = vkTools::initializers::imageMemoryBarrier(); - postPresentBarrier.srcAccessMask = 0; - postPresentBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - postPresentBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; - postPresentBarrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - postPresentBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - postPresentBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - postPresentBarrier.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; - postPresentBarrier.image = swapChain.buffers[currentBuffer].image; - - vkCmdPipelineBarrier( - postPresentCmdBuffer, - VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - 0, - 0, nullptr, - 0, nullptr, - 1, &postPresentBarrier); - - VK_CHECK_RESULT(vkEndCommandBuffer(postPresentCmdBuffer)); -*/ // Submit post present image barrier to transform the image back to a color attachment that our render pass can write to VkSubmitInfo submitInfo = vkTools::initializers::submitInfo(); @@ -712,33 +683,6 @@ void VulkanExampleBase::submitFrame() submitInfo.pSignalSemaphores = &semaphores.renderComplete; } - // Submit a pre present image barrier to the queue - // Transforms the (framebuffer) image layout from color attachment to present(khr) for presenting to the swap chain - /* - VkCommandBufferBeginInfo cmdBufInfo = vkTools::initializers::commandBufferBeginInfo(); - VK_CHECK_RESULT(vkBeginCommandBuffer(prePresentCmdBuffer, &cmdBufInfo)); - - VkImageMemoryBarrier prePresentBarrier = vkTools::initializers::imageMemoryBarrier(); - prePresentBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - prePresentBarrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; - prePresentBarrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - prePresentBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - prePresentBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - prePresentBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - prePresentBarrier.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; - prePresentBarrier.image = swapChain.buffers[currentBuffer].image; - - vkCmdPipelineBarrier( - prePresentCmdBuffer, - VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - VK_FLAGS_NONE, - 0, nullptr, // No memory barriers, - 0, nullptr, // No buffer barriers, - 1, &prePresentBarrier); - - VK_CHECK_RESULT(vkEndCommandBuffer(prePresentCmdBuffer)); - */ // Submit pre present image barrier to transform the image from color attachment to present(khr) for presenting to the swap chain VkSubmitInfo submitInfo = vkTools::initializers::submitInfo(); submitInfo.commandBufferCount = 1; @@ -750,7 +694,7 @@ void VulkanExampleBase::submitFrame() VK_CHECK_RESULT(vkQueueWaitIdle(queue)); } -VulkanExampleBase::VulkanExampleBase(bool enableValidation) +VulkanExampleBase::VulkanExampleBase(bool enableValidation, PFN_GetEnabledFeatures enabledFeaturesFn) { // Check for validation command line flag #if defined(_WIN32) @@ -773,6 +717,11 @@ VulkanExampleBase::VulkanExampleBase(bool enableValidation) initxcbConnection(); #endif + if (enabledFeaturesFn != nullptr) + { + this->enabledFeatures = enabledFeaturesFn(); + } + #if !defined(__ANDROID__) // Android Vulkan initialization is handled in APP_CMD_INIT_WINDOW event initVulkan(enableValidation); diff --git a/base/vulkanexamplebase.h b/base/vulkanexamplebase.h index 0f763276..d8236a4d 100644 --- a/base/vulkanexamplebase.h +++ b/base/vulkanexamplebase.h @@ -50,6 +50,9 @@ #define GAMEPAD_BUTTON_R1 0x1005 #define GAMEPAD_BUTTON_START 0x1006 +// Function pointer for getting physical device fetures to be enabled +typedef VkPhysicalDeviceFeatures (*PFN_GetEnabledFeatures)(); + class VulkanExampleBase { private: @@ -59,6 +62,9 @@ private: bool enableDebugMarkers = false; // Set tot true if v-sync will be forced for the swapchain bool enableVSync = false; + // Device features enabled by the example + // If not set, no additional features are enabled (may result in validation layer errors) + VkPhysicalDeviceFeatures enabledFeatures = {}; // fps timer (one second interval) float fpsTimer = 0.0f; // Create application wide Vulkan instance @@ -208,7 +214,7 @@ public: #endif // Default ctor - VulkanExampleBase(bool enableValidation); + VulkanExampleBase(bool enableValidation, PFN_GetEnabledFeatures enabledFeaturesFn = nullptr); // dtor ~VulkanExampleBase(); @@ -228,7 +234,6 @@ public: void initxcbConnection(); void handleEvent(const xcb_generic_event_t *event); #endif - // Pure virtual render function (override in derived class) virtual void render() = 0; // Called when view change occurs @@ -368,7 +373,7 @@ public: // OS specific macros for the example main entry points #if defined(_WIN32) // Windows entry point -#define VULKAN_EXAMPLE_MAIN(enabledfeatures) \ +#define VULKAN_EXAMPLE_MAIN() \ VulkanExample *vulkanExample; \ LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) \ { \ @@ -391,7 +396,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLin #elif defined(__ANDROID__) // Android entry point // A note on app_dummy(): This is required as the compiler may otherwise remove the main entry point of the application -#define VULKAN_EXAMPLE_MAIN(enabledfeatures) \ +#define VULKAN_EXAMPLE_MAIN() \ VulkanExample *vulkanExample; \ void android_main(android_app* state) \ { \ @@ -407,7 +412,7 @@ void android_main(android_app* state) \ #elif defined(__linux__) // Linux entry point // todo: extract command line arguments -#define VULKAN_EXAMPLE_MAIN( enabledfeatures) \ +#define VULKAN_EXAMPLE_MAIN() \ VulkanExample *vulkanExample; \ static void handleEvent(const xcb_generic_event_t *event) \ { \