diff options
| author | Dustin Graves <dustin@lunarg.com> | 2016-03-03 14:17:08 -0700 |
|---|---|---|
| committer | Dustin Graves <dustin@lunarg.com> | 2016-03-07 12:06:57 -0700 |
| commit | 5aefef01499d849a090b5af5143efce45bf0ebea (patch) | |
| tree | 0c9469d1fcd6953d42261d36f53961ed04f93cc2 | |
| parent | 9d7503f4d1563d1be2e8fcdea9a4e8e33f1bd541 (diff) | |
| download | usermoji-5aefef01499d849a090b5af5143efce45bf0ebea.tar.xz | |
layers: Add param checks for CreateInstance/Device
Add parameter checks for vkCreateDevice and vkCreateInstance.
Includes a local fix for GitHub Vulkan-Docs issue #104 to
prevent false positives from being generated for the
pCreateInfo->pEnabledFeatures == NULL case.
Change-Id: I1f3642e7e18c8bfb32b0996b6e2e57a5f9d8e011
| -rw-r--r-- | generator.py | 33 | ||||
| -rw-r--r-- | layers/param_checker.cpp | 71 | ||||
| -rw-r--r-- | vk.xml | 2 |
3 files changed, 63 insertions, 43 deletions
diff --git a/generator.py b/generator.py index cdca69ab..702627f3 100644 --- a/generator.py +++ b/generator.py @@ -2708,8 +2708,8 @@ class ParamCheckerOutputGenerator(OutputGenerator): self.INDENT_SPACES = 4 # Commands to ignore self.blacklist = [ - 'vkCreateInstance', 'vkCreateDevice', - 'vkGetInstanceProcAddr', 'vkGetDeviceProcAddr', + 'vkGetInstanceProcAddr', + 'vkGetDeviceProcAddr', 'vkEnumerateInstanceLayerProperties', 'vkEnumerateInstanceExtensionsProperties', 'vkEnumerateDeviceLayerProperties', @@ -2735,7 +2735,7 @@ class ParamCheckerOutputGenerator(OutputGenerator): if indent: return indent + inc return inc - + # def decIndent(self, indent): if indent and (len(indent) > self.INDENT_SPACES): return indent[:-self.INDENT_SPACES] @@ -3032,8 +3032,13 @@ class ParamCheckerOutputGenerator(OutputGenerator): lines = cmd.cdecl[:-1].split('\n') # Replace Vulkan prototype lines[0] = 'static VkBool32 param_check_' + cmd.name + '(' - # Replace the first argument with debug_report_data - lines[1] = ' debug_report_data*'.ljust(self.genOpts.alignFuncParam) + 'report_data,' + # Replace the first argument with debug_report_data, when the first + # argument is a handle (not vkCreateInstance) + reportData = ' debug_report_data*'.ljust(self.genOpts.alignFuncParam) + 'report_data,' + if cmd.name != 'vkCreateInstance': + lines[1] = reportData + else: + lines.insert(1, reportData) return '\n'.join(lines) # # Generate the code to check for a NULL dereference before calling the @@ -3129,8 +3134,6 @@ class ParamCheckerOutputGenerator(OutputGenerator): checkExpr = 'skipCall |= validate_array(report_data, {}, "{ln}", {dn}, {pf}{ln}, {pf}{vn}, {}, {});\n'.format(name, cvReq, req, ln=lenParam.name, dn=valueDisplayName, vn=value.name, pf=valuePrefix) elif not value.isoptional: checkExpr = 'skipCall |= validate_required_pointer(report_data, {}, {}, {}{vn});\n'.format(name, valueDisplayName, valuePrefix, vn=value.name) - else: - unused.append(value.name) # # If this is a pointer to a struct, see if it contains members # that need to be checked @@ -3145,8 +3148,6 @@ class ParamCheckerOutputGenerator(OutputGenerator): # The name prefix used when reporting an error with a struct member (eg. the 'pCreateInfor->' in 'pCreateInfo->sType') prefix = '(std::string({}) + std::string("{}.")).c_str()'.format(variablePrefix, value.name) if variablePrefix else '"{}."'.format(value.name) checkExpr += 'skipCall |= param_check_{}(report_data, {}, {}, &({}{}));\n'.format(value.type, name, prefix, valuePrefix, value.name) - elif not value.iscount: - unused.append(value.name) # # Append the parameter check to the function body for the current command if checkExpr: @@ -3156,6 +3157,10 @@ class ParamCheckerOutputGenerator(OutputGenerator): funcBody += self.genCheckedLengthCall(indent, lenParam.name, checkExpr) else: funcBody += indent + checkExpr + elif not value.iscount: + # The parameter is not checked (counts will be checked with + # their associated array) + unused.append(value.name) return funcBody, unused # # Post-process the collected struct member data to create a list of structs @@ -3224,8 +3229,12 @@ class ParamCheckerOutputGenerator(OutputGenerator): cmdDef += '{\n' # Process unused parameters # Ignore the first dispatch handle parameter, which is not - # processed by param_check - for name in unused[1:]: + # processed by param_check (except for vkCreateInstance, which + # does not have a handle as its first parameter) + startIndex = 1 + if command.name == 'vkCreateInstance': + startIndex = 0 + for name in unused[startIndex:]: cmdDef += indent + 'UNUSED_PARAMETER({});\n'.format(name) if len(unused) > 1: cmdDef += '\n' @@ -3235,5 +3244,3 @@ class ParamCheckerOutputGenerator(OutputGenerator): cmdDef += indent + 'return skipCall;\n' cmdDef += '}\n' self.appendSection('command', cmdDef) - - diff --git a/layers/param_checker.cpp b/layers/param_checker.cpp index cf8c76f0..8dcfec16 100644 --- a/layers/param_checker.cpp +++ b/layers/param_checker.cpp @@ -1797,49 +1797,59 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance( const VkAllocationCallbacks* pAllocator, VkInstance* pInstance) { - VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; - VkBool32 skipCall = VK_FALSE; + VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; - if (skipCall == VK_FALSE) { - VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO); - assert(chain_info->u.pLayerInfo); - PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr; - PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance) fpGetInstanceProcAddr(NULL, "vkCreateInstance"); - if (fpCreateInstance == NULL) { - return VK_ERROR_INITIALIZATION_FAILED; - } + VkLayerInstanceCreateInfo *chain_info = + get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO); + assert(chain_info->u.pLayerInfo); + PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = + chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr; + PFN_vkCreateInstance fpCreateInstance = + (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance"); + if (fpCreateInstance == NULL) { + return VK_ERROR_INITIALIZATION_FAILED; + } - // Advance the link info for the next element on the chain - chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext; + // Advance the link info for the next element on the chain + chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext; - result = fpCreateInstance(pCreateInfo, pAllocator, pInstance); - if (result != VK_SUCCESS) - return result; + result = fpCreateInstance(pCreateInfo, pAllocator, pInstance); + if (result != VK_SUCCESS) { + return result; + } - layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map); - VkLayerInstanceDispatchTable *pTable = initInstanceTable(*pInstance, fpGetInstanceProcAddr, pc_instance_table_map); + layer_data *my_data = + get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map); + VkLayerInstanceDispatchTable *pTable = initInstanceTable( + *pInstance, fpGetInstanceProcAddr, pc_instance_table_map); - my_data->report_data = debug_report_create_instance( - pTable, - *pInstance, - pCreateInfo->enabledExtensionCount, - pCreateInfo->ppEnabledExtensionNames); + my_data->report_data = debug_report_create_instance( + pTable, *pInstance, pCreateInfo->enabledExtensionCount, + pCreateInfo->ppEnabledExtensionNames); - InitParamChecker(my_data, pAllocator); - } + InitParamChecker(my_data, pAllocator); // Ordinarily we'd check these before calling down the chain, but none of the layer // support is in place until now, if we survive we can report the issue now. - layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map); + layer_data *my_instance_data = + get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map); + + param_check_vkCreateInstance(my_instance_data->report_data, pCreateInfo, + pAllocator, pInstance); + if (pCreateInfo->pApplicationInfo) { if (pCreateInfo->pApplicationInfo->pApplicationName) { - skipCall |= validate_string(my_device_data, "vkCreateInstance()", "VkInstanceCreateInfo->VkApplicationInfo->pApplicationName", - pCreateInfo->pApplicationInfo->pApplicationName); + validate_string( + my_instance_data, "vkCreateInstance()", + "VkInstanceCreateInfo->VkApplicationInfo->pApplicationName", + pCreateInfo->pApplicationInfo->pApplicationName); } if (pCreateInfo->pApplicationInfo->pEngineName) { - skipCall |= validate_string(my_device_data, "vkCreateInstance()", "VkInstanceCreateInfo->VkApplicationInfo->pEngineName", - pCreateInfo->pApplicationInfo->pEngineName); + validate_string( + my_instance_data, "vkCreateInstance()", + "VkInstanceCreateInfo->VkApplicationInfo->pEngineName", + pCreateInfo->pApplicationInfo->pEngineName); } } @@ -2237,6 +2247,9 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice( VkBool32 skipCall = VK_FALSE; layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map); + skipCall |= param_check_vkCreateDevice(my_instance_data->report_data, + pCreateInfo, pAllocator, pDevice); + if ((pCreateInfo->enabledLayerCount > 0) && (pCreateInfo->ppEnabledLayerNames != NULL)) { for (auto i = 0; i < pCreateInfo->enabledLayerCount; i++) { skipCall |= validate_string(my_instance_data, "vkCreateDevice()", "VkDeviceCreateInfo->ppEnabledLayerNames", @@ -488,7 +488,7 @@ maintained in the master branch of the Khronos Vulkan Github project. <member optional="true" len="enabledLayerCount,null-terminated">const <type>char</type>* const* <name>ppEnabledLayerNames</name></member> <!-- Ordered list of layer names to be enabled --> <member optional="true"><type>uint32_t</type> <name>enabledExtensionCount</name></member> <member optional="true" len="enabledExtensionCount,null-terminated">const <type>char</type>* const* <name>ppEnabledExtensionNames</name></member> - <member>const <type>VkPhysicalDeviceFeatures</type>* <name>pEnabledFeatures</name></member> + <member optional="true">const <type>VkPhysicalDeviceFeatures</type>* <name>pEnabledFeatures</name></member> <validity> <usage>Any given element of pname:ppEnabledLayerNames must: be the name of a layer present on the system, exactly matching a string returned in the sname:VkLayerProperties structure by fname:vkEnumerateDeviceLayerProperties</usage> <usage>Any given element of pname:ppEnabledExtensionNames must: be the name of an extension present on the system, exactly matching a string returned in the sname:VkExtensionProperties structure by fname:vkEnumerateDeviceExtensionProperties</usage> |
