1 /* 2 * Copyright (c) 2015-2016 The Khronos Group Inc. 3 * Copyright (c) 2015-2016 Valve Corporation 4 * Copyright (c) 2015-2016 LunarG, Inc. 5 * Copyright (C) 2015-2016 Google Inc. 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 * Author: Courtney Goeltzenleuchter <courtney (at) LunarG.com> 20 * Author: Jon Ashburn <jon (at) lunarg.com> 21 * 22 */ 23 24 #include "vk_loader_platform.h" 25 #include "loader.h" 26 27 // CreateMsgCallback is global and needs to be 28 // applied to all layers and ICDs. 29 // What happens if a layer is enabled on both the instance chain 30 // as well as the device chain and a call to CreateMsgCallback is made? 31 // Do we need to make sure that each layer / driver only gets called once? 32 // Should a layer implementing support for CreateMsgCallback only be allowed (?) 33 // to live on one chain? Or maybe make it the application's responsibility. 34 // If the app enables DRAW_STATE on at both CreateInstance time and CreateDevice 35 // time, CreateMsgCallback will call the DRAW_STATE layer twice. Once via 36 // the instance chain and once via the device chain. 37 // The loader should only return the DEBUG_REPORT extension as supported 38 // for the GetGlobalExtensionSupport call. That should help eliminate one 39 // duplication. 40 // Since the instance chain requires us iterating over the available ICDs 41 // and each ICD will have it's own unique MsgCallback object we need to 42 // track those objects to give back the right one. 43 // This also implies that the loader has to intercept vkDestroyObject and 44 // if the extension is enabled and the object type is a MsgCallback then 45 // we must translate the object into the proper ICD specific ones. 46 // DestroyObject works on a device chain. Should not be what's destroying 47 // the MsgCallback object. That needs to be an instance thing. So, since 48 // we used an instance to create it, we need a custom Destroy that also 49 // takes an instance. That way we can iterate over the ICDs properly. 50 // Example use: 51 // CreateInstance: DEBUG_REPORT 52 // Loader will create instance chain with enabled extensions. 53 // TODO: Should validation layers be enabled here? If not, they will not be in 54 // the instance chain. 55 // fn = GetProcAddr(INSTANCE, "vkCreateMsgCallback") -> point to loader's 56 // vkCreateMsgCallback 57 // App creates a callback object: fn(..., &MsgCallbackObject1) 58 // Have only established the instance chain so far. Loader will call the 59 // instance chain. 60 // Each layer in the instance chain will call down to the next layer, 61 // terminating with 62 // the CreateMsgCallback loader terminator function that creates the actual 63 // MsgCallbackObject1 object. 64 // The loader CreateMsgCallback terminator will iterate over the ICDs. 65 // Calling each ICD that supports vkCreateMsgCallback and collect answers in 66 // icd_msg_callback_map here. 67 // As result is sent back up the chain each layer has opportunity to record the 68 // callback operation and 69 // appropriate MsgCallback object. 70 // ... 71 // Any reports matching the flags set in MsgCallbackObject1 will generate the 72 // defined callback behavior 73 // in the layer / ICD that initiated that report. 74 // ... 75 // CreateDevice: MemTracker:... 76 // App does not include DEBUG_REPORT as that is a global extension. 77 // TODO: GetExtensionSupport must not report DEBUG_REPORT when using instance. 78 // App MUST include any desired validation layers or they will not participate 79 // in the device call chain. 80 // App creates a callback object: fn(..., &MsgCallbackObject2) 81 // Loader's vkCreateMsgCallback is called. 82 // Loader sends call down instance chain - this is a global extension - any 83 // validation layer that was 84 // enabled at CreateInstance will be able to register the callback. Loader will 85 // iterate over the ICDs and 86 // will record the ICD's version of the MsgCallback2 object here. 87 // ... 88 // Any report will go to the layer's report function and it will check the flags 89 // for MsgCallbackObject1 90 // and MsgCallbackObject2 and take the appropriate action as indicated by the 91 // app. 92 // ... 93 // App calls vkDestroyMsgCallback( MsgCallbackObject1 ) 94 // Loader's DestroyMsgCallback is where call starts. DestroyMsgCallback will be 95 // sent down instance chain 96 // ending in the loader's DestroyMsgCallback terminator which will iterate over 97 // the ICD's destroying each 98 // ICD version of that MsgCallback object and then destroy the loader's version 99 // of the object. 100 // Any reports generated after this will only have MsgCallbackObject2 available. 101 102 void debug_report_add_instance_extensions(const struct loader_instance *inst, struct loader_extension_list *ext_list); 103 104 void debug_report_create_instance(struct loader_instance *ptr_instance, const VkInstanceCreateInfo *pCreateInfo); 105 106 bool debug_report_instance_gpa(struct loader_instance *ptr_instance, const char *name, void **addr); 107 108 VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugReportCallbackEXT(VkInstance instance, 109 const VkDebugReportCallbackCreateInfoEXT *pCreateInfo, 110 const VkAllocationCallbacks *pAllocator, 111 VkDebugReportCallbackEXT *pCallback); 112 113 VKAPI_ATTR void VKAPI_CALL terminator_DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback, 114 const VkAllocationCallbacks *pAllocator); 115 116 VKAPI_ATTR void VKAPI_CALL terminator_DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, 117 VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location, 118 int32_t msgCode, const char *pLayerPrefix, const char *pMsg); 119 120 VkResult util_CreateDebugReportCallback(struct loader_instance *inst, VkDebugReportCallbackCreateInfoEXT *pCreateInfo, 121 const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT callback); 122 123 void util_DestroyDebugReportCallback(struct loader_instance *inst, VkDebugReportCallbackEXT callback, 124 const VkAllocationCallbacks *pAllocator); 125 126 VkResult util_CopyDebugReportCreateInfos(const void *pChain, const VkAllocationCallbacks *pAllocator, uint32_t *num_callbacks, 127 VkDebugReportCallbackCreateInfoEXT **infos, VkDebugReportCallbackEXT **callbacks); 128 void util_FreeDebugReportCreateInfos(const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackCreateInfoEXT *infos, 129 VkDebugReportCallbackEXT *callbacks); 130 VkResult util_CreateDebugReportCallbacks(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator, 131 uint32_t num_callbacks, VkDebugReportCallbackCreateInfoEXT *infos, 132 VkDebugReportCallbackEXT *callbacks); 133 134 void util_DestroyDebugReportCallbacks(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator, uint32_t num_callbacks, 135 VkDebugReportCallbackEXT *callbacks); 136 137 VkBool32 util_DebugReportMessage(const struct loader_instance *inst, VkFlags msgFlags, VkDebugReportObjectTypeEXT objectType, 138 uint64_t srcObject, size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg); 139