layers: switch obj tracker to use text VUIDs
Swap all VU enums for the spec-derived text VUs.
Update object_tracker_generator.py to build an object_tracker.cpp
that uses text VUIDs instead of enums. The script validates vuid
strings directly from validusage.json file. Removes dependency on
vuid_mapping.py and vk_validation_error_messages.h.
Change-Id: I32a209083110200eb16ce1d26fc1d19926759ca4
diff --git a/scripts/object_tracker_generator.py b/scripts/object_tracker_generator.py
index 9e0a375..f24f5c1 100644
--- a/scripts/object_tracker_generator.py
+++ b/scripts/object_tracker_generator.py
@@ -1,9 +1,9 @@
#!/usr/bin/python3 -i
#
-# Copyright (c) 2015-2017 The Khronos Group Inc.
-# Copyright (c) 2015-2017 Valve Corporation
-# Copyright (c) 2015-2017 LunarG, Inc.
-# Copyright (c) 2015-2017 Google Inc.
+# Copyright (c) 2015-2018 The Khronos Group Inc.
+# Copyright (c) 2015-2018 Valve Corporation
+# Copyright (c) 2015-2018 LunarG, Inc.
+# Copyright (c) 2015-2018 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -18,12 +18,12 @@
# limitations under the License.
#
# Author: Mark Lobodzinski <mark@lunarg.com>
+# Author: Dave Houlton <daveh@lunarg.com>
-import os,re,sys,string
+import os,re,sys,string,json
import xml.etree.ElementTree as etree
from generator import *
from collections import namedtuple
-from vuid_mapping import *
from common_codegen import *
# This is a workaround to use a Python 2.7 and 3.x compatible syntax.
@@ -191,42 +191,42 @@
# which is translated here into a good VU. Saves ~40 checks.
self.manual_vuids = dict()
self.manual_vuids = {
- "fence-compatalloc": "VALIDATION_ERROR_24e008c2",
- "fence-nullalloc": "VALIDATION_ERROR_24e008c4",
- "event-compatalloc": "VALIDATION_ERROR_24c008f4",
- "event-nullalloc": "VALIDATION_ERROR_24c008f6",
- "buffer-compatalloc": "VALIDATION_ERROR_23c00736",
- "buffer-nullalloc": "VALIDATION_ERROR_23c00738",
- "image-compatalloc": "VALIDATION_ERROR_252007d2",
- "image-nullalloc": "VALIDATION_ERROR_252007d4",
- "shaderModule-compatalloc": "VALIDATION_ERROR_26a00888",
- "shaderModule-nullalloc": "VALIDATION_ERROR_26a0088a",
- "pipeline-compatalloc": "VALIDATION_ERROR_25c005fc",
- "pipeline-nullalloc": "VALIDATION_ERROR_25c005fe",
- "sampler-compatalloc": "VALIDATION_ERROR_26600876",
- "sampler-nullalloc": "VALIDATION_ERROR_26600878",
- "renderPass-compatalloc": "VALIDATION_ERROR_264006d4",
- "renderPass-nullalloc": "VALIDATION_ERROR_264006d6",
- "descriptorUpdateTemplate-compatalloc": "VALIDATION_ERROR_248002c8",
- "descriptorUpdateTemplate-nullalloc": "VALIDATION_ERROR_248002ca",
- "imageView-compatalloc": "VALIDATION_ERROR_25400806",
- "imageView-nullalloc": "VALIDATION_ERROR_25400808",
- "pipelineCache-compatalloc": "VALIDATION_ERROR_25e00606",
- "pipelineCache-nullalloc": "VALIDATION_ERROR_25e00608",
- "pipelineLayout-compatalloc": "VALIDATION_ERROR_26000256",
- "pipelineLayout-nullalloc": "VALIDATION_ERROR_26000258",
- "descriptorSetLayout-compatalloc": "VALIDATION_ERROR_24600238",
- "descriptorSetLayout-nullalloc": "VALIDATION_ERROR_2460023a",
- "semaphore-compatalloc": "VALIDATION_ERROR_268008e4",
- "semaphore-nullalloc": "VALIDATION_ERROR_268008e6",
- "queryPool-compatalloc": "VALIDATION_ERROR_26200634",
- "queryPool-nullalloc": "VALIDATION_ERROR_26200636",
- "bufferView-compatalloc": "VALIDATION_ERROR_23e00752",
- "bufferView-nullalloc": "VALIDATION_ERROR_23e00754",
- "surface-compatalloc": "VALIDATION_ERROR_26c009e6",
- "surface-nullalloc": "VALIDATION_ERROR_26c009e8",
- "framebuffer-compatalloc": "VALIDATION_ERROR_250006fa",
- "framebuffer-nullalloc": "VALIDATION_ERROR_250006fc",
+ "fence-compatalloc": "\"VUID-vkDestroyFence-fence-01121\"",
+ "fence-nullalloc": "\"VUID-vkDestroyFence-fence-01122\"",
+ "event-compatalloc": "\"VUID-vkDestroyEvent-event-01146\"",
+ "event-nullalloc": "\"VUID-vkDestroyEvent-event-01147\"",
+ "buffer-compatalloc": "\"VUID-vkDestroyBuffer-buffer-00923\"",
+ "buffer-nullalloc": "\"VUID-vkDestroyBuffer-buffer-00924\"",
+ "image-compatalloc": "\"VUID-vkDestroyImage-image-01001\"",
+ "image-nullalloc": "\"VUID-vkDestroyImage-image-01002\"",
+ "shaderModule-compatalloc": "\"VUID-vkDestroyShaderModule-shaderModule-01092\"",
+ "shaderModule-nullalloc": "\"VUID-vkDestroyShaderModule-shaderModule-01093\"",
+ "pipeline-compatalloc": "\"VUID-vkDestroyPipeline-pipeline-00766\"",
+ "pipeline-nullalloc": "\"VUID-vkDestroyPipeline-pipeline-00767\"",
+ "sampler-compatalloc": "\"VUID-vkDestroySampler-sampler-01083\"",
+ "sampler-nullalloc": "\"VUID-vkDestroySampler-sampler-01084\"",
+ "renderPass-compatalloc": "\"VUID-vkDestroyRenderPass-renderPass-00874\"",
+ "renderPass-nullalloc": "\"VUID-vkDestroyRenderPass-renderPass-00875\"",
+ "descriptorUpdateTemplate-compatalloc": "\"VUID-vkDestroyDescriptorUpdateTemplate-descriptorSetLayout-00356\"",
+ "descriptorUpdateTemplate-nullalloc": "\"VUID-vkDestroyDescriptorUpdateTemplate-descriptorSetLayout-00357\"",
+ "imageView-compatalloc": "\"VUID-vkDestroyImageView-imageView-01027\"",
+ "imageView-nullalloc": "\"VUID-vkDestroyImageView-imageView-01028\"",
+ "pipelineCache-compatalloc": "\"VUID-vkDestroyPipelineCache-pipelineCache-00771\"",
+ "pipelineCache-nullalloc": "\"VUID-vkDestroyPipelineCache-pipelineCache-00772\"",
+ "pipelineLayout-compatalloc": "\"VUID-vkDestroyPipelineLayout-pipelineLayout-00299\"",
+ "pipelineLayout-nullalloc": "\"VUID-vkDestroyPipelineLayout-pipelineLayout-00300\"",
+ "descriptorSetLayout-compatalloc": "\"VUID-vkDestroyDescriptorSetLayout-descriptorSetLayout-00284\"",
+ "descriptorSetLayout-nullalloc": "\"VUID-vkDestroyDescriptorSetLayout-descriptorSetLayout-00285\"",
+ "semaphore-compatalloc": "\"VUID-vkDestroySemaphore-semaphore-01138\"",
+ "semaphore-nullalloc": "\"VUID-vkDestroySemaphore-semaphore-01139\"",
+ "queryPool-compatalloc": "\"VUID-vkDestroyQueryPool-queryPool-00794\"",
+ "queryPool-nullalloc": "\"VUID-vkDestroyQueryPool-queryPool-00795\"",
+ "bufferView-compatalloc": "\"VUID-vkDestroyBufferView-bufferView-00937\"",
+ "bufferView-nullalloc": "\"VUID-vkDestroyBufferView-bufferView-00938\"",
+ "surface-compatalloc": "\"VUID-vkDestroySurfaceKHR-surface-01267\"",
+ "surface-nullalloc": "\"VUID-vkDestroySurfaceKHR-surface-01268\"",
+ "framebuffer-compatalloc": "\"VUID-vkDestroyFramebuffer-framebuffer-00893\"",
+ "framebuffer-nullalloc": "\"VUID-vkDestroyFramebuffer-framebuffer-00894\"",
}
# Commands shadowed by interface functions and are not implemented
@@ -246,29 +246,32 @@
# Named tuples to store struct and command data
self.StructType = namedtuple('StructType', ['name', 'value'])
self.CmdMemberData = namedtuple('CmdMemberData', ['name', 'members'])
+ self.CmdMemberAlias = dict()
self.CmdInfoData = namedtuple('CmdInfoData', ['name', 'cmdinfo'])
self.CmdExtraProtect = namedtuple('CmdExtraProtect', ['name', 'extra_protect'])
self.CommandParam = namedtuple('CommandParam', ['type', 'name', 'ispointer', 'isconst', 'isoptional', 'iscount', 'len', 'extstructs', 'cdecl', 'islocal', 'iscreate', 'isdestroy', 'feature_protect'])
self.StructMemberData = namedtuple('StructMemberData', ['name', 'members'])
self.object_types = [] # List of all handle types
self.valid_vuids = set() # Set of all valid VUIDs
- self.vuid_file = None
+ self.vuid_dict = dict() # VUID dictionary (from JSON)
# Cover cases where file is built from scripts directory, Lin/Win, or Android build structure
# Set cwd to the script directory to more easily locate the header.
previous_dir = os.getcwd()
os.chdir(os.path.dirname(sys.argv[0]))
vuid_filename_locations = [
- './vk_validation_error_messages.h',
- '../layers/vk_validation_error_messages.h',
- '../../layers/vk_validation_error_messages.h',
- '../../../layers/vk_validation_error_messages.h',
+ './Vulkan-Headers/registry/validusage.json',
+ '../Vulkan-Headers/registry/validusage.json',
+ '../../Vulkan-Headers/registry/validusage.json',
+ '../../../Vulkan-Headers/registry/validusage.json'
]
for vuid_filename in vuid_filename_locations:
if os.path.isfile(vuid_filename):
- self.vuid_file = open(vuid_filename, "r", encoding="utf8")
+ json_file = open(vuid_filename, 'r')
+ self.vuid_dict = json.load(json_file)
+ json_file.close()
break
- if self.vuid_file == None:
- print("Error: Could not find vk_validation_error_messages.h")
+ if len(self.vuid_dict) == 0:
+ print("Error: Could not find, or error loading validusage.json")
sys.exit(1)
os.chdir(previous_dir)
#
@@ -299,23 +302,19 @@
isoptional = True;
return isoptional
#
- # Convert decimal number to 8 digit hexadecimal lower-case representation
- def IdToHex(self, dec_num):
- if dec_num > 4294967295:
- print ("ERROR: Decimal # %d can't be represented in 8 hex digits" % (dec_num))
- sys.exit()
- hex_num = hex(dec_num)
- return hex_num[2:].zfill(8)
- #
# Get VUID identifier from implicit VUID tag
- def GetVuid(self, vuid_string):
+ def GetVuid(self, parent, suffix):
+ vuid_string = 'VUID-%s-%s' % (parent, suffix)
+ vuid = "kVUIDUndefined"
if '->' in vuid_string:
- return "VALIDATION_ERROR_UNDEFINED"
- vuid_num = self.IdToHex(convertVUID(vuid_string))
- if vuid_num in self.valid_vuids:
- vuid = "VALIDATION_ERROR_%s" % vuid_num
+ return vuid
+ if vuid_string in self.valid_vuids:
+ vuid = "\"%s\"" % vuid_string
else:
- vuid = "VALIDATION_ERROR_UNDEFINED"
+ if parent in self.CmdMemberAlias:
+ alias_string = 'VUID-%s-%s' % (self.CmdMemberAlias[parent], suffix)
+ if alias_string in self.valid_vuids:
+ vuid = "\"%s\"" % vuid_string
return vuid
#
# Increases indent by 4 spaces and tracks it globally
@@ -343,7 +342,7 @@
# Generate the object tracker undestroyed object validation function
def GenReportFunc(self):
output_func = ''
- output_func += 'void ReportUndestroyedObjects(VkDevice device, enum UNIQUE_VALIDATION_ERROR_CODE error_code) {\n'
+ output_func += 'void ReportUndestroyedObjects(VkDevice device, std::string error_code) {\n'
output_func += ' DeviceReportUndestroyedObjects(device, kVulkanObjectTypeCommandBuffer, error_code);\n'
for handle in self.object_types:
if self.isHandleTypeNonDispatchable(handle):
@@ -364,19 +363,28 @@
return output_func
#
+ # Walk the JSON-derived dict and find all "vuid" key values
+ def ExtractVUIDs(self, d):
+ if hasattr(d, 'items'):
+ for k, v in d.items():
+ if k == "vuid":
+ yield v
+ elif isinstance(v, dict):
+ for s in self.ExtractVUIDs(v):
+ yield s
+ elif isinstance (v, list):
+ for l in v:
+ for s in self.ExtractVUIDs(l):
+ yield s
+
+ #
# Called at beginning of processing as file is opened
def beginFile(self, genOpts):
OutputGenerator.beginFile(self, genOpts)
- # Open vk_validation_error_messages.h file to verify computed VUIDs
- for line in self.vuid_file:
- # Grab hex number from enum definition
- vuid_list = line.split('0x')
- # If this is a valid enumeration line, remove trailing comma and CR
- if len(vuid_list) == 2:
- vuid_num = vuid_list[1][:-2]
- # Make sure this is a good hex number before adding to set
- if len(vuid_num) == 8 and all(c in string.hexdigits for c in vuid_num):
- self.valid_vuids.add(vuid_num)
+ # Build a set of all vuid text strings found in validusage.json
+ for json_vuid_string in self.ExtractVUIDs(self.vuid_dict):
+ self.valid_vuids.add(json_vuid_string)
+
# File Comment
file_comment = '// *** THIS FILE IS GENERATED - DO NOT EDIT ***\n'
file_comment += '// See object_tracker_generator.py for modifications\n'
@@ -386,10 +394,10 @@
copyright += '\n'
copyright += '/***************************************************************************\n'
copyright += ' *\n'
- copyright += ' * Copyright (c) 2015-2017 The Khronos Group Inc.\n'
- copyright += ' * Copyright (c) 2015-2017 Valve Corporation\n'
- copyright += ' * Copyright (c) 2015-2017 LunarG, Inc.\n'
- copyright += ' * Copyright (c) 2015-2017 Google Inc.\n'
+ copyright += ' * Copyright (c) 2015-2018 The Khronos Group Inc.\n'
+ copyright += ' * Copyright (c) 2015-2018 Valve Corporation\n'
+ copyright += ' * Copyright (c) 2015-2018 LunarG, Inc.\n'
+ copyright += ' * Copyright (c) 2015-2018 Google Inc.\n'
copyright += ' *\n'
copyright += ' * Licensed under the Apache License, Version 2.0 (the "License");\n'
copyright += ' * you may not use this file except in compliance with the License.\n'
@@ -404,6 +412,7 @@
copyright += ' * limitations under the License.\n'
copyright += ' *\n'
copyright += ' * Author: Mark Lobodzinski <mark@lunarg.com>\n'
+ copyright += ' * Author: Dave Houlton <daveh@lunarg.com>\n'
copyright += ' *\n'
copyright += ' ****************************************************************************/\n'
write(copyright, file=self.outFile)
@@ -722,8 +731,8 @@
param = -2
compatalloc_vuid_string = '%s-compatalloc' % cmd_info[param].name
nullalloc_vuid_string = '%s-nullalloc' % cmd_info[param].name
- compatalloc_vuid = self.manual_vuids.get(compatalloc_vuid_string, "VALIDATION_ERROR_UNDEFINED")
- nullalloc_vuid = self.manual_vuids.get(nullalloc_vuid_string, "VALIDATION_ERROR_UNDEFINED")
+ compatalloc_vuid = self.manual_vuids.get(compatalloc_vuid_string, "kVUIDUndefined")
+ nullalloc_vuid = self.manual_vuids.get(nullalloc_vuid_string, "kVUIDUndefined")
if self.isHandleTypeObject(cmd_info[param].type) == True:
if object_array == True:
# This API is freeing an array of handles -- add loop control
@@ -742,14 +751,14 @@
decl_code = ''
pre_call_code = ''
post_call_code = ''
- param_vuid_string = 'VUID-%s-%s-parameter' % (parent_name, obj_name)
- parent_vuid_string = 'VUID-%s-%s-parent' % (parent_name, obj_name)
- param_vuid = self.GetVuid(param_vuid_string)
- parent_vuid = self.GetVuid(parent_vuid_string)
+ param_suffix = '%s-parameter' % (obj_name)
+ parent_suffix = '%s-parent' % (obj_name)
+ param_vuid = self.GetVuid(parent_name, param_suffix)
+ parent_vuid = self.GetVuid(parent_name, parent_suffix)
+
# If no parent VUID for this member, look for a commonparent VUID
- if parent_vuid == 'VALIDATION_ERROR_UNDEFINED':
- commonparent_vuid_string = 'VUID-%s-commonparent' % parent_name
- parent_vuid = self.GetVuid(commonparent_vuid_string)
+ if parent_vuid == 'kVUIDUndefined':
+ parent_vuid = self.GetVuid(parent_name, 'commonparent')
if obj_count is not None:
pre_call_code += '%s for (uint32_t %s = 0; %s < %s; ++%s) {\n' % (indent, index, index, obj_count, index)
indent = self.incIndent(indent)
@@ -913,6 +922,8 @@
isdestroy=isdestroy,
feature_protect=self.featureExtraProtect))
self.cmdMembers.append(self.CmdMemberData(name=cmdname, members=membersInfo))
+ if alias != None:
+ self.CmdMemberAlias[cmdname] = alias
self.cmd_info_data.append(self.CmdInfoData(name=cmdname, cmdinfo=cmdinfo))
self.cmd_feature_protect.append(self.CmdExtraProtect(name=cmdname, extra_protect=self.featureExtraProtect))
#