Add option for protected mode

Specify with --protected_output

Change-Id: Ie517545edbf14cea7e823f1fa271280e2c12e253
Reviewed-on: https://fuchsia-review.googlesource.com/c/third_party/Vulkan-Tools/+/444614
Reviewed-by: John Rosasco <rosasco@google.com>
diff --git a/cube/cube.cpp b/cube/cube.cpp
index 201e392..7506f00 100644
--- a/cube/cube.cpp
+++ b/cube/cube.cpp
@@ -320,6 +320,7 @@
     bool use_xlib;
     bool separate_present_queue;
     uint32_t gpu_number;
+    bool protected_output;
 
     vk::Instance inst;
     vk::PhysicalDevice gpu;
@@ -707,8 +708,14 @@
     queues[0].setQueueFamilyIndex(graphics_queue_family_index);
     queues[0].setQueueCount(1);
     queues[0].setPQueuePriorities(priorities);
+    if (protected_output) {
+        queues[0].setFlags(vk::DeviceQueueCreateFlagBits::eProtected);
+    }
+
+    auto const protected_memory = vk::PhysicalDeviceProtectedMemoryFeatures().setProtectedMemory(protected_output);
 
     auto deviceInfo = vk::DeviceCreateInfo()
+                          .setPNext(&protected_memory)
                           .setQueueCreateInfoCount(1)
                           .setPQueueCreateInfos(queues)
                           .setEnabledLayerCount(0)
@@ -768,7 +775,9 @@
     // engine has fully released ownership to the application, and it is
     // okay to render to the image.
     vk::PipelineStageFlags const pipe_stage_flags = vk::PipelineStageFlagBits::eColorAttachmentOutput;
+    auto const protected_submit_info = vk::ProtectedSubmitInfo().setProtectedSubmit(protected_output);
     auto const submit_info = vk::SubmitInfo()
+                                 .setPNext(&protected_submit_info)
                                  .setPWaitDstStageMask(&pipe_stage_flags)
                                  .setWaitSemaphoreCount(1)
                                  .setPWaitSemaphores(&image_acquired_semaphores[frame_index])
@@ -920,7 +929,9 @@
     VERIFY(result == vk::Result::eSuccess);
 
     vk::CommandBuffer const commandBuffers[] = {cmd};
-    auto const submitInfo = vk::SubmitInfo().setCommandBufferCount(1).setPCommandBuffers(commandBuffers);
+    auto const protected_submit_info = vk::ProtectedSubmitInfo().setProtectedSubmit(protected_output);
+    auto const submitInfo =
+        vk::SubmitInfo().setCommandBufferCount(1).setPCommandBuffers(commandBuffers).setPNext(&protected_submit_info);
 
     result = graphics_queue.submit(1, &submitInfo, fence);
     VERIFY(result == vk::Result::eSuccess);
@@ -944,6 +955,7 @@
     use_xlib = false;
     /* For cube demo we just grab the first physical device by default */
     gpu_number = 0;
+    protected_output = false;
 
     for (int i = 1; i < argc; i++) {
         if (strcmp(argv[i], "--use_staging") == 0) {
@@ -981,11 +993,17 @@
             i++;
             continue;
         }
+        if (strcmp(argv[i], "--protected_output") == 0) {
+            protected_output = true;
+            continue;
+        }
+
         std::stringstream usage;
         usage << "Usage:\n  " << APP_SHORT_NAME << "\t[--use_staging] [--validate]\n"
               << "\t[--break] [--c <framecount>] [--suppress_popups]\n"
               << "\t[--gpu_number <index of physical device>]\n"
               << "\t[--present_mode <present mode enum>]\n"
+              << "\t[--protected_output]\n"
               << "\t<present_mode_enum>\n"
               << "\t\tVK_PRESENT_MODE_IMMEDIATE_KHR = " << VK_PRESENT_MODE_IMMEDIATE_KHR << "\n"
               << "\t\tVK_PRESENT_MODE_MAILBOX_KHR = " << VK_PRESENT_MODE_MAILBOX_KHR << "\n"
@@ -1070,6 +1088,12 @@
     enabled_extension_count = 0;
     enabled_layer_count = 0;
 
+    uint32_t apiVersion = 0;
+    vk::enumerateInstanceVersion(&apiVersion);
+    if (protected_output && apiVersion < VK_MAKE_VERSION(1, 1, 0)) {
+        ERR_EXIT("Need vulkan 1.1 for protected output.", "vkCreateInstance Failure");
+    }
+
     // Look for validation layers
     vk::Bool32 validation_found = VK_FALSE;
     if (validate) {
@@ -1225,7 +1249,7 @@
                          .setApplicationVersion(0)
                          .setPEngineName(APP_SHORT_NAME)
                          .setEngineVersion(0)
-                         .setApiVersion(VK_API_VERSION_1_0);
+                         .setApiVersion(protected_output ? VK_MAKE_VERSION(1, 1, 0) : VK_MAKE_VERSION(1, 0, 0));
     auto const inst_info = vk::InstanceCreateInfo()
                                .setPApplicationInfo(&app)
                                .setEnabledLayerCount(enabled_layer_count)
@@ -1309,6 +1333,10 @@
 
     gpu.getProperties(&gpu_props);
 
+    if (protected_output && gpu_props.apiVersion < VK_MAKE_VERSION(1, 1, 0)) {
+        ERR_EXIT("Need vulkan physical device 1.1 for protected output.", "vkcube");
+    }
+
     /* Call with nullptr data to get count */
     gpu.getQueueFamilyProperties(&queue_family_count, static_cast<vk::QueueFamilyProperties *>(nullptr));
     assert(queue_family_count >= 1);
@@ -1425,7 +1453,16 @@
 
     create_device();
 
-    device.getQueue(graphics_queue_family_index, 0, &graphics_queue);
+    if (protected_output) {
+        auto const queue_info2 = vk::DeviceQueueInfo2()
+                                     .setFlags(vk::DeviceQueueCreateFlagBits::eProtected)
+                                     .setQueueFamilyIndex(graphics_queue_family_index)
+                                     .setQueueIndex(0);
+        device.getQueue2(&queue_info2, &graphics_queue);
+    } else {
+        device.getQueue(graphics_queue_family_index, 0, &graphics_queue);
+    }
+
     if (!separate_present_queue) {
         present_queue = graphics_queue;
     } else {
@@ -1484,7 +1521,10 @@
 }
 
 void Demo::prepare() {
-    auto const cmd_pool_info = vk::CommandPoolCreateInfo().setQueueFamilyIndex(graphics_queue_family_index);
+    auto cmd_pool_info = vk::CommandPoolCreateInfo().setQueueFamilyIndex(graphics_queue_family_index);
+    if (protected_output) {
+        cmd_pool_info.setFlags(vk::CommandPoolCreateFlagBits::eProtected);
+    }
     auto result = device.createCommandPool(&cmd_pool_info, nullptr, &cmd_pool);
     VERIFY(result == vk::Result::eSuccess);
 
@@ -1674,22 +1714,25 @@
         }
     }
 
-    auto const swapchain_ci = vk::SwapchainCreateInfoKHR()
-                                  .setSurface(surface)
-                                  .setMinImageCount(desiredNumOfSwapchainImages)
-                                  .setImageFormat(format)
-                                  .setImageColorSpace(color_space)
-                                  .setImageExtent({swapchainExtent.width, swapchainExtent.height})
-                                  .setImageArrayLayers(1)
-                                  .setImageUsage(vk::ImageUsageFlagBits::eColorAttachment)
-                                  .setImageSharingMode(vk::SharingMode::eExclusive)
-                                  .setQueueFamilyIndexCount(0)
-                                  .setPQueueFamilyIndices(nullptr)
-                                  .setPreTransform(preTransform)
-                                  .setCompositeAlpha(compositeAlpha)
-                                  .setPresentMode(swapchainPresentMode)
-                                  .setClipped(true)
-                                  .setOldSwapchain(oldSwapchain);
+    auto swapchain_ci = vk::SwapchainCreateInfoKHR()
+                            .setSurface(surface)
+                            .setMinImageCount(desiredNumOfSwapchainImages)
+                            .setImageFormat(format)
+                            .setImageColorSpace(color_space)
+                            .setImageExtent({swapchainExtent.width, swapchainExtent.height})
+                            .setImageArrayLayers(1)
+                            .setImageUsage(vk::ImageUsageFlagBits::eColorAttachment)
+                            .setImageSharingMode(vk::SharingMode::eExclusive)
+                            .setQueueFamilyIndexCount(0)
+                            .setPQueueFamilyIndices(nullptr)
+                            .setPreTransform(preTransform)
+                            .setCompositeAlpha(compositeAlpha)
+                            .setPresentMode(swapchainPresentMode)
+                            .setClipped(true)
+                            .setOldSwapchain(oldSwapchain);
+    if (protected_output) {
+        swapchain_ci.setFlags(vk::SwapchainCreateFlagBitsKHR::eProtected);
+    }
 
     result = device.createSwapchainKHR(&swapchain_ci, nullptr, &swapchain);
     VERIFY(result == vk::Result::eSuccess);